锁是Java并发编程中最重要的同步机制。锁除了让临界区互斥执行外,还能够让释放锁的线程向获取同一个锁的线程发送消息。java
线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。编程
线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内存中读取共享变量。数据结构
在共享变量的可见性方面,锁的释放和获取和volatile是相似的。并发
对volatile变量进行写操做,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。atom
对volatile变量进行读操做,JMM会把该线程对应的本地内存置为无效。再从主内存中读取共享变量。线程
锁获取和释放内存处理流程:blog
因为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并发编程艺术》