彻底理解Volatile关键字以及volatile为什么不能保证线程安全
2019-08-27 10:42:05 1 举报
这副图主要是时序图,帮助大家彻底理解volatile关键字的可见性以及volatile为什么不能保证线程安全,结合程序和文字,通俗易懂
作者其他创作
大纲/内容
此时的t1线程栈内存
此时的堆内存
flag:true
volatile count=0
flag:false
我是华丽的分割线
在下面这个例子中,我们可以定义一个竞态变量count。我们希望两个线程能够安全地实现对count的++操作。例如,当两个线程各自对初始值为0的count各执行一次++操作后,count的值应该为2。下面是当我们不用任何同步手段(如synchronized关键字)来保证线程安全情况下,仅使用volatile来约束count变量的一种可能情况:
读取count到本地内存中
此时的主线程栈内存
volatile count=1
v.setFlag(true)
++count
Thread.sleep(2000)
对执行结果的解释
执行结果
一直在while死循环中
打印“线程结束运行并退出”
t1.start()
线程1的本地栈内存
为什么volatile无法保证线程安全性?
flag的本地副本:true
线程2的本地栈内存
由于没有使用Volatile关键字,因此主线程对flag变量的更新对t1线程是不可见的,因此t1线程的本地变量副本的值依然是false,所以线程1会永远陷入死循环中
主线程
Java内存的抽象模型
线程1
线程t1
flag的本地副本:false
在这种情况下,执行了两次count++,但count最后的值为1。这是因为volatile无法将某个线程对竞态变量的读和写操作捆绑为一个原子操作,只有当任意线程的读写操作能够被捆绑为原子操作,即: (某线程读->某线程写) ->(另外某线程读->另外某线程写) 才能够实现线程安全,而volatile并不能保证这一点,它只能保证某个线程对竞态变量的修改可以立即同步到其他线程中,因此volatile不能实现线程安全
当不使用Volatile关键字的时候:
线程2
由于使用了Volatile关键字,因此主线程对flag变量的更新对t1线程是可见的,因此t1线程的本地变量副本的值被修改为true
当使用Volatile关键字的时候:
写回
0 条评论
下一页