一、什么是可见性?
内存可见性(memory visibility)
是指当某个线程正在使用对象状态而另一个线程在同时修改该状态,需要确保当一个线程修改了状态后,其他线程能够立即看到发生的状态变化。
由于线程之间的交互都发生在主内存中,但对于变量的修改又发生在自己的工作内存中,经常会造成读写共享变量的错误,我们也叫可见性错误。
可见性错误是指当读操作与写操作在不同的线程中执行时,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。
解决方案:
Synchronized
volatile
ReentrantLock
CAS
二、Synchronized保证可见性的原理:java内存模型
1,如果线程A要和线程B通讯(发送数据),需要经过两个步骤
首先A需要将副本写到主内存中去,B再去主内存中读取数据,就可以读取到A更新过的共享变量了。这个过程是由我们JVM去控制的。
主内存是A和B沟通的桥梁
JVM正是通过控制主内存与每个线程的本地内存之间的交互来为我们java程序员提供内存可见性的保证。
2,在了解了java内存模型之后呢,我们来学习下Synchronized是如何做到可见性的实现的?
在释放锁之前一定会将数据写回主内存
:
一旦一个代码块或者方法被Synchronized所修饰,那么它执行完毕之后,被锁住的对象所做的任何修改都要在释放之前,从线程内存写回到主内存。也就是说他不会存在线程内存和主内存内容不一致的情况。
在获取锁之后一定从主内存中读取数据
:
同样的,线程在进入代码块得到锁之后,被锁定的对象的数据也是直接从主内存中读取出来的,由于上一个线程在释放的时候会把修改好的内容回写到主内存,所以线程从主内存中读取到数据一定是最新的。
就是通过这样的原理,Synchronized关键字保证了我们每一次的执行都是可靠的,它保证了可见性。