锁可以让临界区互斥执行,还可以让释放锁的线程向获取同一个锁的线程发送消息。
线程A释放一个锁,实质上是线程A向接下来将要获取这个锁的某个线程发出了(线程A对共享变量所做修改的)消息。
线程B获取一个锁,实质上是线程B接收了之前某个线程发出的(在释放这个锁之前对共享变量所做修改的)消息。
线程A释放一个锁,随后线程B获取该锁,这个过程实质是线程A通过主内存向线程B发送消息。
由上可见,锁的释放-获取的内存语义同volatile变量写-读的内存语义相同。
锁释放-获取的内存语义的实现至少有下面两种方式:
由于Java的CAS同时具有volatile读和volatile写的内存语义,因此Java线程之间的通信现在有了下面4中方式:
Java的CAS会使用现代处理器上提供的高效机器级别的院子指令,这些原子指令以原子方式对内存执行读-改-写操作,这是在多处理器中实现同步的关键。 同时,volatile变量的读/写和CAS可以实现线程之间的通信。把这些特性整合在一起,就形成了整个concurrent包得以实现的基石。
观察concurrent包的源码实现,可发现一个通用化的实现模型:
AQS,非阻塞数据结构和原子变量类,这些concurrent包中的基础类都是使用这些模式来实现的,其高层类又是基于这些基础类来实现的。