java 多线程5(volatile关键字)

来源:互联网 发布:韩国历史教科书知乎 编辑:程序博客网 时间:2024/05/16 17:38

synchronized 同步方法、同步代码块能实现多线程在同一时刻只有一个线程能执行同步方法或同步代码块中代码即实现同步代码块的队列执行,下面来看看volatile关键字。

使用volatile关键字增加了实例变量在多个线程之间的可见性但volatile关键字最致命的的缺点是不支持原子性。


synchronized和volatile对比

1、关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量而synchronized可以修饰方法以及代码块。

2、多线程访问volatile不会发生阻塞,而synchronized会出现阻塞。

3、volatile能保证数据的可见性,但不能保证原子性,而synchronized可以保证原子性,也可以间接保证可见性,因为synchronized方法或代码块在结束前会将线程私有内存和公共内存中的数据做同步。

4、关键字volatile解决的是变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性(个人看法:同步性=原子性+可见性)

5、关键字volatile提示线程每次从共享内存中读取变量,而不是从私有内存中读取,当修改后更新了私有内存中的变量的之后会立即刷新共享内存中变量的值,这样就保证了同步数据的可见性。


java 内存模型下变量的处理过程:

                        

1、如果我们不使用volatile关键字来修饰变量则整个执行过程就是:线程从主内存中读取数据到工作内存,在对这个变量进行处理,处理完后将最新的值更新到工作内存中,但是不一定会立马将这个值刷新到主内存中,而如果其他线程这时再从主内存中读取数据到工作内存,在工作内存中进行一系列处理后将这个最新的值赋值给工作内存中的变量,然后在将这个值刷新到主内存中,这时是不是就乱了。这时我们可以使用volatile来实现数据的可见性。

2、使用volatile关键字来修饰变量的话,当刚开始的时候A线程从主存中读取变量到工作内存,如果在工作内存中操作的时候发现有B线程修改了主内存中的变量的值则这时

A线程的工作内存中的这个变量就失效了,所以还要再从主从中获取最新的数据,A线程修改了变量的值后将这个赋给工作内存同时把这个最新的值刷新到主内存中,所以就保证了数据的可见性。

3、如果变量使用volatile关键字来修饰相比不修饰的多做了这些事:

(1)、A线程在工作内存中处理的过程中发现主内存中的变量有修改,则工作内存中的数据失效而会再次从主存中读取最新数据。

(2)、A线程在处理完之后会立马把变量的最新值刷新到主内存中,以便其他线程能及时获取最新值。

对比上图如果使用volatile关键字修饰变量则:

(1)、如果主内存中的变量被其他线程修改,则A线程的工作内存中变量的缓存失效,而再次执行第一步再从主存中读取数据。

(2)、当A线程处理完后执行了第三步后会立马执行第四部即将最新值刷新到主内存中。

同样对比上图如果不使用volatile则:

(1)、如果其他线程修改了主内存中的变量的值,则A线程还在使用原来的值,所以处理后的值就是一个错误的值。

(2)、如果A线程处理完后只执行了第三步即将最新的值赋值给了工作内存而没有及时执行第四步将最新的值刷新到主内存中去而是去执行其他的工作了,则其他线程从主内存中获取数据时,其实获取的就是一个错误的数据。



0 0
原创粉丝点击