多线程基础知识第四篇:volatile的应用

参考https://www.cnblogs.com/dolphin0520/p/3920373.html

写的真是好,解释了原子性、可见性、有序性、指令重排序、内存屏障,要多读几遍才能慢慢理解。

在并发编程中,通常会遇到三个问题:原子性问题、可见性问题、有序性问题。

原子性:一个操作或者多个操作,要么都执行,且执行过程不会被任何因素中断,要么都不执行。在java中,只有对基本类型的变量的赋值和读取是原子操作,如 int i = 10; 是原子操作,而 y = x; 不是原子操作。

可见性:一个线程更新了共享变量的值,其他线程可以立即看到新值。

有序性:代码执行顺序和代码编写顺序一致。

java内存模型(java memory model,简称JMM)规定,每个线程都有自己的工作内存,线程对变量的操作必须在自己的工作内存中进行,不能直接在主存中进行,并且每个线程不能访问其他线程的工作内存。

volatile和可见性、有序性都有关。一个共享变量被volatile修饰,那么就具备了两层语义:

1、保证了多个线程对这个变量进行操作时的可见性,即一个线程修改了这个变量的值,新值对其他线程来说是立即可见的。这是因为volatile会强制立即将新值从修改值的线程的工作内存中写入主存,并且使其他访问这个变量的线程的工作内存中该变量对应的缓存行失效,这样其他线程在访问这个变量时,会把新值读到自己的工作内存中。

2、禁止进行指令重排序。

指令重排序是指处理器为了提高运行效率,可能会对输入代码进行优化,它不保证代码的执行顺序与编写顺序一致,但是它会保证代码的最终执行结果和代码顺序执行的结果是一致的。指令重排序不会影响单线程执行的正确性,但是可能会影响多线程执行的正确性。volatile能禁止指令重排序,当程序执行到操作volatile变量时,在其前面的操作肯定已经执行,在其后面的操作肯定还没执行。

操作volatile变量的代码生成的汇编代码会比操作非volatile变量的代码生成的汇编代码多一个lock前缀的指令,这个lock前缀指令相当于一个内存屏障,屏障前的代码会比屏障后的代码先执行。

posted on 2016-04-06 01:11  koushr  阅读(340)  评论(0编辑  收藏  举报

导航