锁的内存语义

锁是Java并发编程中最重要的同步机制。锁除了让临界区互斥执行外,还能够让释放锁的线程向获取同一个锁的线程发送消息。java

锁的获取和释放

线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。编程

线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内存中读取共享变量。数据结构

在共享变量的可见性方面,锁的释放和获取和volatile是相似的。并发

对volatile变量进行写操做,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。atom

对volatile变量进行读操做,JMM会把该线程对应的本地内存置为无效。再从主内存中读取共享变量。线程

 

锁获取和释放内存处理流程:blog

  • 线程A释放一个锁,实质上是线程A向接下来将要获取这个锁的某个线程发出了(线程A对共享变量所作修改的)消息。
  • 线程B获取一个锁,实质上是线程B接收了以前某个线程发出的(在释放这个锁以前对共享变量所作修改的)消息。
  • 线程A释放锁,随后线程B获取这个锁,这个过程实质上是线程A经过主内存向线程B发送消息。

 

concurrent包的实现

因为Java的CAS同时具备volatile读和volatile写的内存语义,所以Java线程之间的通讯如今有了下面4种方式。
1)A线程写volatile变量,随后B线程读这个volatile变量。
2)A线程写volatile变量,随后B线程用CAS更新这个volatile变量。
3)A线程用CAS更新一个volatile变量,随后B线程用CAS更新这个volatile变量。
4)A线程用CAS更新一个volatile变量,随后B线程读这个volatile变量。内存

Java的CAS会使用现代处理器上提供的高效机器级别的原子指令,这些原子指令以原子方式对内存执行读-改-写操做,这是在多处理器中实现同步的关键。同时,volatile变量的读/写和CAS能够实现线程之间的通讯。把这些特性整合在一块儿,就造成了整个concurrent包得以实现的基石。同步

分析concurrent包的源代码实现,会发现一个通用化的实现模式。基础

首先,声明共享变量为volatile。
而后,使用CAS的原子条件更新来实现线程之间的同步。同时,配合以volatile的读/写和CAS所具备的volatile读和写的内存语义来实现线程之间的通讯。

AQS,非阻塞数据结构和原子变量类(java.util.concurrent.atomic包中的类),这些concurrent包中的基础类都是使用这种模式来实现的,而concurrent包中的高层类又是依赖于这些基础类来实现的。

                    concurrent包的实现示意图

 

 

 

 

 

 

参考:

《Java并发编程艺术》

相关文章
相关标签/搜索