黑马程序员技术交流社区

标题: 深入理解Java内存模型——锁(二) [打印本页]

作者: 李江    时间: 2013-10-8 08:17
标题: 深入理解Java内存模型——锁(二)
本帖最后由 李江 于 2013-10-8 08:18 编辑

锁释放和获取的内存语义

当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。以上面的MonitorExample程序为例,A线程释放锁后,共享数据的状态示意图如下(图二):


当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须要从主内存中去读取共享变量。下面是锁获取的状态示意图(图三):


对比锁释放-获取的内存语义与volatile写-读的内存语义,可以看出:锁释放与volatile写有相同的内存语义;锁获取与volatile读有相同的内存语义。下面对锁释放和锁获取的内存语义做个总结:

锁内存语义的实现本文将借助ReentrantLock的源代码,来分析锁内存语义的具体实现机制。请看下面的示例代码:
  1. class ReentrantLockExample {
  2. int a = 0;
  3. ReentrantLock lock = new ReentrantLock();

  4. public void writer() {
  5.     lock.lock();         //获取锁
  6.     try {
  7.         a++;
  8.     } finally {
  9.         lock.unlock();  //释放锁
  10.     }
  11. }

  12. public void reader () {
  13.     lock.lock();        //获取锁
  14.     try {
  15.         int i = a;
  16.         ……
  17.     } finally {
  18.         lock.unlock();  //释放锁
  19.     }
  20. }
  21. }
复制代码
在ReentrantLock中,调用lock()方法获取锁;调用unlock()方法释放锁。ReentrantLock的实现依赖于java同步器框架AbstractQueuedSynchronizer(本文简称之为AQS)。AQS使用一个整型的volatile变量(命名为state)来维护同步状态,马上我们会看到,这个volatile变量是ReentrantLock内存语义实现的关键。 下面是ReentrantLock的类图(仅画出与本文相关的部分)(图四):




图二.jpg (42.46 KB, 下载次数: 7)

图二

图二

图三.jpg (52.11 KB, 下载次数: 10)

图三

图三

图四.jpg (46.4 KB, 下载次数: 14)

图四

图四





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2