博客
关于我
Java volatile使用详细说明-可见性的详细讲解
阅读量:696 次
发布时间:2019-03-17

本文共 1849 字,大约阅读时间需要 6 分钟。

Java多线程之同步与易失性

在学习多线程编程时,同步和易失性是两个关键概念。前篇已经探讨了同步的骚操作,本篇将深入分析同步状语从句,了解其与易失性之间的区别,易失性的使用条件,以及虚拟机层面的一些实现细节。


本文要点

  • 同步与易失性特性差异
  • 使用易失性需要满足的条件
  • 易失性特性在虚拟机层面的实现
  • 易失性示例代码

  • 1. 同步与易失性特性差异

    1.1 可见性和原子性

    • synchronized保证了可见性和原子性。
    • volatile仅保证可见性,不具备原子性。
    • 可见性是指,一个线程修改了被volatile修饰的变量后,其他线程可以立即发现新值。

    1.2 线程阻塞

    • synchronized可能会导致线程阻塞,因为它争夺资源时会让其他线程等待。
    • volatile不会引起阻塞,因为它不会影响线程的执行流程。

    1.3 依赖性与安全性

    • 当共享数据的改变依赖于其之前的值时,synchronized能保证线程安全,而volatile不适用于这种场景。
    • volatile主要用于标记完成或中断等场景,例如资源是否被释放或信号是否正确传递。

    1.4 修饰方式与重排序

    • synchronized修饰的是方法或代码块,而volatile修饰的是变量。
    • volatile修饰的变量不会被重排序,减少了同步有关的复杂性。

    1.5 虚拟机的规则

    • 从虚拟机的规则来看,volatile变量的写操作总是比后续的读操作先发生。这体现了内存的一致性模型。

    2. 使用易失性需要满足的条件

    2.1 单一修改-authority

    • 变量的修改不能依赖其当前值,并且只能有单一线程能够执行修改操作。

    2.2 不变约束

    • 变量不需要与其他变量完成不变式约束。例如,不需要保证 x + y = k 总是成立,除非这是非多线程环境下的绝对需求。

    2.3 无需额外锁定

    • 使用volatile时不需要额外的锁定机制,因为它不需要保护代码块的可执行性。

    3. 易失性特性在虚拟机层面的实现

    虚拟机通过以下机制确保易失性变量的一致性:

    • 当一个线程修改了被volatile修饰的变量时,其修改操作会立即反映到主内存中。
    • 其他线程在访问该变量时,会直接从主内存中读取当前值,而不是从工作内存中缓存副本。
    • 正常变量的读写操作可能因工作内存的缓存而遮蔽,容易导致多线程环境下的一致性问题。

    4. 易失性示例代码

    4.1 共享变量作为开关

    以下示例代码展示了volatile变量作为开关的应用:

    public class ValiableTest {    public static void main(String[] args) {        boolean isRunning = false;        Thread t1 = new Thread(() -> {            while (isRunning) {                System.out.println("运行中......");                try {                    Thread.sleep(100);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });                new Thread(() -> {            isRunning = false;            System.out.println("下面终止运行");        }).start();                t1.start();    }}
    • volatile修饰:如果不使用volatileisRunning变量在多线程环境下可能不会更新,导致程序无法正常终止。
    • 使用volatile修饰:若isRunningvolatile修饰,主线程的修改会及时反映到其他线程,程序才能正常终止。

    总结

    通过对比synchronizedvolatile的特性,我们可以更好地理解它们各自适用的场景。synchronized更适合保护共享资源的原子性操作,而volatile则用以处理快速变更的状态标记,如资源释放或信号传递。在实际编码中,应该根据具体需求选择合适的机制。

    转载地址:http://kaxhz.baihongyu.com/

    你可能感兴趣的文章
    MySQL I 有福啦,窗口函数大大提高了取数的效率!
    查看>>
    mysql id自动增长 初始值 Mysql重置auto_increment初始值
    查看>>
    MySQL in 太多过慢的 3 种解决方案
    查看>>
    MySQL InnoDB 三大文件日志,看完秒懂
    查看>>
    Mysql InnoDB 数据更新导致锁表
    查看>>
    Mysql Innodb 锁机制
    查看>>
    MySQL InnoDB中意向锁的作用及原理探
    查看>>
    MySQL InnoDB事务隔离级别与锁机制深入解析
    查看>>
    Mysql InnoDB存储引擎 —— 数据页
    查看>>
    Mysql InnoDB存储引擎中的checkpoint技术
    查看>>
    Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
    查看>>
    MySQL InnoDB引擎的锁机制详解
    查看>>
    Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
    查看>>
    mysql InnoDB数据存储引擎 的B+树索引原理
    查看>>
    mysql innodb通过使用mvcc来实现可重复读
    查看>>
    mysql insert update 同时执行_MySQL进阶三板斧(三)看清“触发器 (Trigger)”的真实面目...
    查看>>
    mysql interval显示条件值_MySQL INTERVAL关键字可以使用哪些不同的单位值?
    查看>>
    Mysql join原理
    查看>>
    MySQL Join算法与调优白皮书(二)
    查看>>
    Mysql order by与limit混用陷阱
    查看>>