volatile不保证自增操作原子性
2019-08-27 10:43:21 0 举报
图解volatile不保证自增操作原子性
作者其他创作
大纲/内容
执行a++代码
主内存
5.线程A被唤醒,此时主存中a的真实值已经被线程B修改成了1,而线程A手上的a'之前已经读取了是0,下一步要执行的是加运算,它不会再回过头读取a的最新值,于是,a'的值0和1完成加运算0+1=1。
线程A
读
int a=0
4.线程B正准备span style=\"font-size: inherit;\
2.线程B拿到执行权,开始执行 I、II、III,顺利执行完毕
a刷新为1
I.从主存中拷贝a=0到工作内存的副本a'中
原来在多线程环境下,竞争实在太激烈了!执行a++是线程不安全的,线程A还没来得及将a和1做加运算,线程就被挂起了,之后再想做加运算的时候,操作的共享变量值可能已经发生了变化。这次加运算是个无用的写操作。相当于白做了一次a++操作!因此,在多线程环境下,就算加了volatile关键字,还是无法保证原子性。
7.将运算结果1赋值给a'
注意:单纯地读取主存共享变量a的值这一操作是原子操作,但是执行a'和1的加运算是先读取a的值赋给a',再执行加运算,这是两步。这两步一起做无法保证原子性,也就是说,真正执行加运算的时候,a’的值可能已经被修改了,等真正a'做完加运算后,回过头才发现,a'使用的并不是最新的主存中的a=1,而是一个过期a'=0。a'没能拿着共享变量a的最新值和1做加运算。
3.由于线程B修改了共享变量的副本值a',主存中a的值被即时刷新为a=a'=1,这个操作也会使得其他所有线程的工作内存中副本a'的引用失效,其他线程必须重新来主存拷贝共享变量a的值。
8.由于线程A修改了共享变量的副本值a'=0+1=1,主存中a的值被即时刷新为a=a'=1
写
1.执行完 I ,正要执进行a'和1的加运算时发生线程阻塞线程A进入休眠
2: getfield #12 5: iconst_1 6: iadd 7: putfield #12
线程B
收藏
0 条评论
下一页