zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java并发——volatile的原理

JAVA并发原理 volatile
2023-09-11 14:21:18 时间

volatile关键字就是Java中提供的另一种解决可见性和有序性问题的方案。对于原子性,需要强调一点,也是大家容易误解的一点:对volatile变量的单次读/写操作可以保证原子性的,如long和double类型变量,但是并不能保证i++这种操作的原子性,因为本质上i++是读、写两次操作。

1 volatile的原理 1.1 可见性

在前文中已经提及过,线程本身并不直接与主内存进行数据的交互,而是通过线程的工作内存来完成相应的操作。这也是导致线程间数据不可见的本质原因。因此要实现volatile变量的可见性,直接从这方面入手即可。对volatile变量的写操作与普通变量的主要区别有两点:

修改volatile变量时会强制将修改后的值刷新的主内存中 修改volatile变量后会导致其他线程工作内存中对应的变量值失效。因此,再读取该变量值的时候就需要重新从读取主内存中的值。

通过这两个操作,就可以解决volatile变量的可见性问题。

1.2 原子性

volatile只能保证对单次读/写的原子性。因为long和double两种数据类型的操作可分为高32位和低32位两部分,因此普通的long或double类型读/写可能不是原子的。因此,鼓励大家将共享的long和double变量设置为volatile类型,这样能保证任何情况下对long和double的单次读/写操作都具有原子性。

1.3 顺序性

在解释这个问题前,我们先来了解一下Java中的happen-before规则:如果a happen-before b,则a所做的任何操作对b是可见的。

JSR 133中定义的happen-before规则有:

同一个线程中的,前面的操作 happen-before 后续的操作。(即单线程内按代码顺序执行。但是,在不影响在单线程环境执行结果的前提下,编译器和处理器可以进行重排序,这是合法的。换句话说,这一是规则无法保证编译重排和指令重排) 监视器上的解锁操作 happen-before 其后续的加锁操作。(Synchronized 规则) 对volatile变量的写操作 happen-before 后续的读操作。(volatile 规则) 线程的start() 方法 happen-before 该线程所有的后续操作。(线程启动规则) 线程所有的操作 happen-before 其他线程在该线程上调用 join 返回成功后的操作 如果 a happen-before b,b happen-before c,则a happen-before c(传递性) 1.4 内存屏障

为了实现volatile可见性和happen-befor的语义。JVM底层是通过一个叫做“内存屏障”的东西来完成。内存屏障,也叫做内存栅栏,是一组处理器指令,用于实现对内存操作的顺序限制。下面是完成上述规则所要求的内存屏障:

LoadLoad 屏障

执行顺序:Load1— Loadload— Load2

确保Load2及后续Load指令加载数据之前能访问到Load1加载的数据。

StoreStore 屏障

执行顺序:Store1— StoreStore— Store2

确保Store2以及后续Store指令执行前,Store1操作的数据对其它处理器可见。

LoadStore 屏障

执行顺序: Load1— LoadStore— Store2

确保Store2和后续Store指令执行前,可以访问到Load1加载的数据。

StoreLoad 屏障

执行顺序: Store1— StoreLoad— Load2

确保Load2和后续的Load指令读取之前,Store1的数据对其他处理器是可见的。


大数据开发基础的编程语言的Java的并发/多线程编程的并发编程基础 Java是一种流行的面向对象编程语言,它支持并发/多线程编程。在多线程应用中,多个线程可以同时执行,提高程序的效率和性能。但是,在多线程编程中,需要注意线程安全和同步问题。本文将介绍Java的并发编程基础以及如何避免线程安全和同步问题。
大数据开发基础的编程语言的Java的并发/多线程编程的线程池 Java并发编程中,线程池是一种非常重要的工具,通过线程池可以有效地管理多个线程,并提高程序的可扩展性和效率。本文将介绍Java的线程池以及如何使用线程池进行多线程编程。
大数据开发基础的编程语言的Java的并发/多线程编程的锁 在Java并发编程中,锁是一种非常重要的机制,用于保证多个线程之间访问共享资源的安全性。本文将介绍Java的锁机制以及如何使用锁进行多线程编程。
大数据开发基础的编程语言的Java的并发/多线程编程的原子类 在Java并发编程中,原子类是一种非常重要的机制,用于保证多个线程之间对于共享变量的访问的原子性。本文将介绍Java的原子类以及如何使用原子类进行多线程编程。
大数据开发基础的编程语言的Java的并发/多线程编程的并发容器 在Java并发编程中,使用并发容器可以提高多线程环境下的数据访问效率和安全性。本文将介绍Java的并发容器以及如何使用它们进行多线程编程。
大数据开发基础的编程语言的Java的并发/多线程编程的JUC并发工具类 在Java并发编程中,JUC(java.util.concurrent)包中的并发工具类提供了各种功能强大的工具来协调多线程之间的执行和通信。本文将介绍Java的JUC并发工具类以及如何使用它们进行多线程编程。