博客
关于我
并发编程——Volatile
阅读量:339 次
发布时间:2019-03-04

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

摘要

本文主要分析了Java中的Volatile关键字及其在内存模型中的作用。通过对Java内存模型(JMM)的理解,深入探讨了Volatile如何保证共享变量的可见性及其在多线程环境中的重要性。

测试案例

测试案例通过展示了多线程环境中Volatile关键字的行为,帮助理解其在实际应用中的表现。

Java内存模型(JMM)

Java内存模型(JMM)是Java虚拟机规范中定义的内存模型,它屏蔽了底层不同计算机硬件的差异。现代计算机的CPU与内存速度差距巨大,引入高速缓存(Cache)缓冲了这一问题,但也带来了缓存一致性(CacheCoherence)的挑战。在多处理器系统中,各个处理器共享同一主内存,每个处理器都有自己的缓存。

JMM的规定

JMM规定所有共享变量(实例变量和类变量)存储于主内存,而线程工作内存只维护自身变量的副本。线程操作变量必须在工作内存完成,不能直接读写主内存。

本地内存与主内存的关系

本地内存(Local Memory)与主内存(MainMemory)之间的关系通过缓存一致性协议维持。MESI协议是常见的缓存一致性协议,它通过嗅探总线数据检测缓存状态。

可见性解决方案

加锁可以通过同步工作内存与主内存的状态,确保线程操作的可见性。Volatile通过禁止指令重排序和强制从主内存读取数据,保证了可见性。

为何加锁可以解决可见性问题

加锁机制确保线程在操作共享变量时,工作内存与主内存保持一致。线程获得锁时会清空工作内存,执行完操作后刷新主内存。

Volatile修饰共享变量

Volatile确保线程操作共享变量时的可见性。每个线程读取数据时都会从主内存获取最新值,保证多线程环境下的正确性。

Volatile的作用

Volatile禁止指令重排序,确保单线程程序语义不变。它不仅保证可见性,还能通过强制从主内存读写数据,防止指令重排序带来的潜在问题。

MESI缓存一致性协议

MESI协议通过嗅探总线数据,检测缓存状态。当缓存行被修改时,其他处理器会无效化旧缓存,重新从主内存读取数据。

嗅探的缺点

嗅探会导致总线带宽浪费,尤其在多线程环境下,不适用于大量使用Volatile的情况。应谨慎选择合适的同步机制。

禁止指令重排序

JMM限制了编译器和处理器对指令重排序的方式,确保指令执行顺序符合程序语义。Volatile通过内存屏障禁止特定重排序,保证了内存模型的正确性。

内存屏障

内存屏障插入到指令序列中,禁止特定类型的重排序。Volatile写操作前后插入屏障,确保数据可见性。读操作后插入两个屏障,保证读取到最新数据。

Happens-before关系

Happens-before关系确保两个操作之间存在可见性。Volatile写操作总是先于后续读操作。

无法保证原子性

Volatile不能确保原子性,多线程读写可能导致不一致。需要结合其他机制如Atomic类来保证线程安全。

双重检查问题

双重检查用于确保对象初始化的可见性。Volatile通过禁止指令重排序,解决了双重检查中的潜在问题。

Volatile与Synchronized的区别

Volatile只能修饰共享变量,不能修饰方法和代码块。它提供可见性但不保证原子性,适用于特定场景下的轻量级同步。

Atomic的实现方式

Atomic类通过Unsafe实现原子性操作,使用CAS算法保证多线程安全。

CAS的局限性

CAS算法可能导致ABA问题,且在高并发下效率不高。

总结

Volatile在多线程环境中发挥重要作用,通过可见性和禁止重排序确保程序正确性。它适用于特定场景下的轻量级同步,但需要结合其他机制确保原子性。

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

你可能感兴趣的文章
Quartz入门看这一篇文章就够了
查看>>
POI解析Excel【poi的坑——空行处理】
查看>>
POI:POI+JXL实现xls文件添加水印
查看>>
POI:POI实现docx文件添加水印
查看>>
POJ 1006
查看>>
Quartz中时间表达式的设置-----corn表达式
查看>>
poj 1035
查看>>
POJ 1061 青蛙的约会 (扩展欧几里得)
查看>>
Quartz2.2.1简单使用
查看>>
POJ 1080 Human Gene Functions(DP:LCS)
查看>>
Quant 开源项目教程
查看>>
POJ 1088 滑雪
查看>>
POJ 1095 Trees Made to Order
查看>>
POJ 1113 Wall(计算几何--凸包的周长)
查看>>
poj 1125Stockbroker Grapevine(最短路)
查看>>
Qualitor processVariavel.php 未授权命令注入漏洞复现(CVE-2023-47253)
查看>>
poj 1151 (未完成) 扫描线 线段树 离散化
查看>>
POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并
查看>>
poj 1163 数塔
查看>>
POJ 1177 Picture(线段树:扫描线求轮廓周长)
查看>>