很多新手对于如何理解JavaVolatile关键词不是很清楚。为了帮助大家解决这个问题,下面小编就为大家详细讲解一下。需要的人可以从中学习,希望你能有所收获。
正文
在谈论Volatile之前,我们先来回顾一下Java内存模型的三个要素:原子性、可见性和有序性,这是我们经常提到的并发编程的三个要素。
并发编程的三要素
1.原子性
和数据库事务中的原子性一样,满足原子性特征的操作是不能中断的,要么所有操作都成功,要么所有操作都失败。
只有简单的读取和赋值(数字必须赋给变量,变量之间的赋值不是原子操作)才是原子操作。
比如:
I=2;j=I;我;I=I 1;
在以上四个操作中,i=2是读操作,必须是原子操作。如果你认为这是原子操作。其实分为两步。一种是读取I的值,然后赋给j,这是两步操作,不是原子操作。I和i=i 1实际上是等价的。读取I的值,加1,然后写回主存。这是一个三步走的操作。
因此,在上面的例子中,最终值可能会有很多情况,只是因为原子性无法得到满足。
非原子操作会有线程安全问题,所以我们需要用同步化技术把它变成原子操作。java的并发包提供了一些原子类,比如AtomicInteger、AtomicLong等。
00-1010当多个线程访问同一个共享变量时,如果一个线程修改了这个共享变量的值,其他线程可以立即获得修改后的值。
00-1010编译器和处理器会对指令序列进行重新排序,以优化程序性能,也就是说,您编写的代码序列与您最终执行的指令序列不一致。但是,重排序过程不会影响单线程程序的执行,反而会影响多线程并发执行的正确性。
2.可见性
Volatile是Java语言的类型修饰符。一旦共享变量(类的成员变量和类的静态成员变量)被Volatile修改,它就有两层语义:
1.确保多线程下的可见性。
2.禁止对指令进行重新排序(即保证顺序)。
在这里,我们需要注意一个问题。挥发只能让他修饰的内容看得见、有条不紊。Volatile只能保证单个读/写的原子性,我这个操作不能保证原子性。
3.有序性
**Java内存模型(JMM)**是一个抽象的概念,实际上并不存在。它描述了一套规则或规范。通过这组规范,定义了程序中各种变量(包括实例字段、静态字段和构成数组对象的元素)的访问方法。
尽量屏蔽各种硬件和操作系统之间的内存访问差异,让Java程序在各种平台下都能达到一致的内存访问效果。
Java内存模型规定,所有变量都存储在主内存,每个线程都有自己的工作记忆。线程的工作内存保存着线程中使用的变量的主内存副本。线程对变量的所有操作都必须在工作内存中进行,而不是直接读写主内存。不同的线程不能直接访问对方工作内存中的变量,线程之间的变量传递需要自己的工作内存和主内存之间的数据同步。
主存主要存储Java实例对象,线程创建的所有实例对象都存储在主存中,不管实例对象是方法中的成员变量还是局部变量(也叫局部变量),当然也包括共享类信息、常量和静态变量。因为它是一个共享数据区,所以多个线程在访问同一个变量时可能会发现线程安全问题。
工作内存每个线程都有自己的工作内存(工作内存,也称为本地内存,可以与前面提到的处理器缓存进行比较)。线程的工作内存在线程使用的变量的主内存中保存共享变量的副本。
工作记忆是JMM的一个抽象概念,并不真正存在。它涵盖了高速缓存、写缓冲区、寄存器以及其他硬件和编译器优化。
存储当前方法的所有局部变量信息(工作内存在主内存中存储变量的副本)。每个线程只能访问自己的工作内存,也就是说,线程中的局部变量对其他线程是不可见的。即使两个线程正在执行同一段代码,它们也会在自己的工作内存中创建属于当前线程的本地变量,包括字节码行号指示符和相关的Native方法信息。
Volatile
Volatile 保证内存可见性
Java Volatile关键字如何理解">
主内存和工作内存之间的交互有具体的交互协议,JMM定义了 八种操作 来完成,这八种操作是 原子的 、 不可再分的 ,它们分别是:lock
,unlock
,read
,load
,use
,assign
,store
,write
。
其中,lock , unlock , read , write 作用于主内存; load ,use , assign , store 作用于工作内存。
(1) lock
将主内存中的变量锁定,为一个线程所独占。
(2) unclock
将lock加的锁定解除,此时其它的线程可以有机会访问此变量。
(3) read
将主内存中的变量值读到工作内存当中。
(4) load
将read读取的值保存到工作内存中的变量副本中。
(5) use
将值传递给线程的代码执行引擎。
(6) assign
将执行引擎处理返回的值重新赋值给变量副本。
(7) store
将变量副本的值存储到主内存中。
(8) write
将 store 存储的值写入到主内存的共享变量当中。
-
从主存复制变量到当前工作内存(read and load)
-
执行代码,改变共享变量值 (use and assign)
-
用工作内存数据刷新主存相关内容 (store and write)
指令规则
-
read 和 load、store 和 write 必须成对出现。
-
assign 操作,工作内存变量改变后必须刷回主内存。
-
同一时间只能运行一个线程对变量进行 lock,当前线程 lock 可重入,unlock 次数必须等于 lock 的次数,该变量才能解锁。
-
对一个变量 lock 后,会清空该线程工作内存变量的值,重新执行 load 或者 assign 操作初始化工作内存中变量的值。
-
unlock 前,必须将变量同步到主内存( store/write 操作)。
Volatile源码案例
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/154817.html