锁的内存语义

锁可以让临界区互斥执行。

锁的释放和获取的内存语义

当线程释放锁时,JMM(Java内存模型)把该线程对应的本地内存中的共享变量刷新到主内存中。
在这里插入图片描述

当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内存中读取共享变量。
在这里插入图片描述

对比锁释放-获取的内存语义与volatile写-读的内存语义可以看出:锁释放与volatile写有相同的内存语义;锁获取与volatile读有相同的内存语义。

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

锁内存语义的实现

ReentrantLock中,调用lock()方法获取锁;调用unlock()方法释放锁。
学习笔记:独占锁ReentrantLock的原理
ReentrantLock公平锁及非公平锁实现

ReentrantLock的实现依赖于Java同步器框架AbstractQueuedSynchronizer(AQS)。
AQS使用一个整型的volatile变量来维护同步状态:private volatile int state;

公平锁:加锁方法lock()调用轨迹:

  1. ReentrantLock:lock()
  2. FairSync:lock()
  3. AbstractQueuedSynchronizer:acquire()
  4. ReetrantLock$FairSync:tryAcquire()
    在这里插入图片描述
    加锁方法首先读volatile变量state:int c = getState();

公平锁:解锁方法unlock()调用轨迹:

  1. ReentrantLock:unlock()
  2. AbstractQueuedSynchronizer:release()
  3. ReetrantLock$Sync:tryRelease()

在这里插入图片描述
在释放锁的最后写volatile变量state:setState(c);

公平锁在释放锁的最后写volatile变量state,在获取锁时首先读这个volatile变量state。根据volatile的happens-before规则,释放锁的线程在写volatile变量之前可见的共享变量,在获取锁的线程读取同一个volatile变量后将立即变得对获取锁的线程可见。

非公平锁:加锁方法lock()调用轨迹:

  1. ReentrantLock:lock()
  2. NonfairSync:lock()
  3. AbstractQueuedSynchronizer:compareAndSetState()

在这里插入图片描述

   protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

该方法以原子操作的方式更新state变量。

JDK文档对CAS方法的说明如下:如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。此操作具有volatile读和写的内存语义
编译器不能对CAS与CAS前面和后面的任意内存操作重排序。

  • 公平锁和非公平锁释放时,最后都要写一个volatile变量state
  • 公平锁获取时,首先会去读volatile变量
  • 非公平锁获取时,首先会用CAS更新volatile变量,这个操作同时具有volatile读和volatile写的内存语义。

从以上对ReentrantLock的分析可以看出,锁释放-获取的内存语义实现至少有下面两种方式:

  1. 利用volatile变量的写-读所具有的内存语义。
  2. 利用CAS所附带的volatile读和volatile写的内存语义。

《Java并发编程的艺术》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值