博客
关于我
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
    查看>>
    MySQL
    查看>>
    mysql
    查看>>
    MTK Android 如何获取系统权限
    查看>>
    MySQL - 4种基本索引、聚簇索引和非聚索引、索引失效情况、SQL 优化
    查看>>
    MySQL - ERROR 1406
    查看>>
    mysql - 视图
    查看>>
    MySQL - 解读MySQL事务与锁机制
    查看>>
    MTTR、MTBF、MTTF的大白话理解
    查看>>
    mt_rand
    查看>>
    mysql -存储过程
    查看>>
    mysql /*! 50100 ... */ 条件编译
    查看>>
    mudbox卸载/完美解决安装失败/如何彻底卸载清除干净mudbox各种残留注册表和文件的方法...
    查看>>
    mysql 1264_关于mysql 出现 1264 Out of range value for column 错误的解决办法
    查看>>
    mysql 1593_Linux高可用(HA)之MySQL主从复制中出现1593错误码的低级错误
    查看>>
    mysql 5.6 修改端口_mysql5.6.24怎么修改端口号
    查看>>
    MySQL 8.0 恢复孤立文件每表ibd文件
    查看>>
    MySQL 8.0开始Group by不再排序
    查看>>
    mysql ansi nulls_SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON 什么意思
    查看>>
    multi swiper bug solution
    查看>>