1.Volatile特性

  1. 可见性-对于一个Volatile变量的读,总能看得到任意线程对这个Volatil最后的写入
  2. 原子性,对于任意单个Volatile的读写具有原子性,类型Volatil++复合操作不具有原子性

2.Volatile保证内存可见性

  当写一个Volatiel变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中,并会让其他读该Volatiel变量线程的本地内存无效,去主内存读取。

  1. 线程A写一个Volatiel变量时,实际上是A线程向接下将要读取这个Volatiel变量的某个线程发出了消息(共享变量的修改)
  2. 线程B读取一个Volatiel变量,实际上是B线程接收之前某个线程发出的消息
  3. 线程A写Volatiel变量,线程B读Volatiel变量,这个过程实际上就是线程A通过主内存向线程B发送消息

07-Volatile进阶与锁

3.Volatile内存屏障

  我们在使用Volatile时会插入内存屏障来做禁止重排,分别有下面4种

  1. 在每个Volatile写操作的前面插入一个StoreStroe屏障
  2. 在每个Volatile写操作的后面插入一个StoreLoad屏障
  3. 在每个Volatile读操作的后面插入一个LoadLoad屏障
  4. 在每个Volatile读操作的后面插入一个LoadStore屏障

StoreStroe屏障的意思是说,禁止Volatile写操作上面的写操作与当前Volatile写操作重排序

StoreLoad屏障的意思是说,禁止Volatile写操作与下面的Volatile读写操作重排序

LoadLoad屏障的意思是说,禁止Volatile读操作下面所有普通读与Volatile读操作重排

LoadStore屏障的意思是说,禁止Volatile读操作下面所有普通写与Volatile写操作重排

4.锁

  锁是Java重要的同步机制,锁除了让临界互斥执行外,还可以让释放锁与获取锁的线程通信,锁里面不会禁止线程临界区重排优化,因为互斥,其他阻塞线程观察不到当前线程中的重排。

07-Volatile进阶与锁

  锁的底层是由同步器实现的(AQS),同步器底层依靠CAS、Volatile变量。

5.锁的内存可见性保证

  当线程释放锁时,JMM会把该线程对应的本地内存共享比哪里刷新到主内存中,当某个线程获取锁时JMM会把这个线程对应的本地内存设置为无效,去主内存读取。

07-Volatile进阶与锁

  1. 线程A释放锁时,实际上是A线程向接下将要读取这个锁的某个线程发出了消息(共享变量的修改)
  2. 线程B获取到锁,实际上是B线程接收之前某个线程发出的消息
  3. 线程A释放锁,线程B获取锁,这个过程实际上就是线程A通过主内存向线程B发送消息
6.对比Volatile与锁

对比Volatile与锁的内存可见性可以发现,锁的释放与Volatile的写一样,锁的获取与Volatile的读一样,Volati的读写与锁的释放获取有相同的效果

参考:

《Java并发编程的艺术》

相关文章:

  • 2021-05-09
  • 2021-08-22
  • 2021-06-03
  • 2021-12-27
  • 2022-12-23
  • 2021-09-21
  • 2021-11-11
  • 2021-06-26
猜你喜欢
  • 2021-06-28
  • 2021-11-15
  • 2022-12-23
  • 2021-10-28
  • 2021-10-29
  • 2021-09-13
相关资源
相似解决方案