多线程之内存可见性和原子性
-
可见性:一个线程/进程对共享变量的修改能够及时被其它的线程/进程看到
原子性:即操作不可再分(在汇编层面看为一条机器指令),比如a = 1, 和 return a 分别具有原子性, 但 “a += b”可能需要经过三个步骤:
- mov eax,dword ptr [a]
- add eax,dword ptr [b]
- mov dword ptr [a],eax
-
voliate 仅保证可见性, 不保证操作原子性
-
Volatile实现内存可见性是通过store和load指令完成的;也就是对volatile变量执行写操作时,会在写操作后加入一条store指令,即强迫线程/进程将最新的值刷新到主内存中;而在读操作时,会加入一条load指令,即强迫从主内存中读入变量的值。但volatile不保证volatile变量的原子性,例如:
voliate int a = 0;
a++; //不是原子操作
//可以分为:读取a的值,将a的值+1,写入最新的a的值。
//对于a++;操作,线程1和线程2都执行一次,
//最后输出a的值可能是:1或者2
/*
【解释】输出结果1的解释:当线程1执行a++;语句时,先是读入a的值为0,倘若此时让出CPU执行权,线程获得执行,线程2会重新从主内存中,读入a的值还是0,然后线程2执行+1操作,最后把a=1刷新到主内存中; 线程2执行完后,线程1由开始执行,但之前已经读取的a的值0,所以它还是在0的基础上执行+1操作,也就是还是等于1,并刷新到主内存中。所以最终的结果是1
一般在多线程/进程中使用volatile变量,为了安全,对变量的写入操作不能依赖当前变量的值:如a++或者a=a*5这些操作。
*/