深挖锁(补充篇)

简介: 本文阅读大概需要8分钟。


一前记


针对公众号关注者针对Lock,synchronized和cmpxchg提出的疑问,这里特意补充一片来分析一下Lock和synchronized区别,以及cmpxchg的意义。


二Lock和synchronized的区别


我们在深挖锁上篇已经知道synchronized是由javac编译成moniterenter和moniterexit指令实现代码同步块的,也就是说synchronized的同步实现是由JVM对moniterenter与moniterexit指令的执行来实现的。而Lock类相关的锁实现是不依赖于JVM的虚拟机指令实现,而是直接通过java代码实现的。这里我们以重入锁ReetrantLock的lock方法的实现来说明:


static final class NonfairSync extends Sync {
    private static final long serialVersionUID = 7316153563782823691L;
    /**
     * Performs lock.  Try immediate barge, backing up to normal
     * acquire on failure.
     */
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }
    ...//省略
}


这里我们以ReentrantLock默认的非公平锁来进行分析,这里可以看到NonfairSync.lock()便是ReentrantLock.lock()的实现方法。ReentrantLock获取锁首先通过compareAndSetState()尝试将锁对象的state标志由期望值0设置为1,如果设置成功,则说明成功获取了锁,如果失败则通过调用同步队列的acquire()方法,将线程加入同步队列进行锁等待。这里compareAndSetState便是获取锁的关键实现,下面便是compareAndSetState的实现:


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


如果看过之前面“试题13解析-CAS与ABA”的同学应该对这个函数不陌生,正是CAS原子操作系列的函数,在处理器级别,CAS的原子性是由处理器对cmpxchg汇编指令加入LOCK_IF_MP前缀所提供的内存屏障进行保证的(深挖锁上篇),而synchronized对应的moniter虚拟机指令的也同样是由cmpxchg实现的。这里我们一定要理解原子性与锁是不同的概念,CAS为锁的加解锁操作提供了原子性操作的保证,但是CAS并不代表锁,CAS提供的是变量原子性操作的功能,例如Atomic包中的类的实现也是通过CAS来对变量进行原子性操作的。


其实,锁可以抽象成一个标记,线程尝试获取锁的过程,就是尝试将该标记设置为已上锁的过程,只要我们能保证只有一个线程可以成功设置该标记(即上锁过程的原子性),那么这个标记就是一把锁。Lock与synchronized(moniter指令)获取锁与释放锁过程中正是使用CAS来设置锁标志的。


Lock接口是JDK5之后提供的锁机制,其相对于关键字synchronized为程序员提供了更灵活的加锁解锁接口,以及公平锁非公平锁等更多的锁特性,本文意在解释原子性与锁的关系,为了避免陷入Lock实现的细节,因此这里就不展开说明Lock接口以及Lock实现依赖的同步队列AbstractQueuedSynchronizer的相关内容了。最后说一下区别synchronized是在JVM中实现的,而Lock的锁逻辑是Java层直接实现的。

相关文章
|
5月前
|
Java
探秘死锁:原理、发生条件及解决方案
探秘死锁:原理、发生条件及解决方案
118 1
|
6月前
|
算法 Java
Java多线程基础-13:一文阐明死锁的成因及解决方案
死锁是指多个线程相互等待对方释放资源而造成的一种僵局,导致程序无法正常结束。发生死锁需满足四个条件:互斥、请求与保持、不可抢占和循环等待。避免死锁的方法包括设定加锁顺序、使用银行家算法、设置超时机制、检测与恢复死锁以及减少共享资源。面试中可能会问及死锁的概念、避免策略以及实际经验。
99 1
|
6月前
|
Java 开发者
你知道偏向锁已经被废弃了吗?谈谈你对此的看法。
你知道偏向锁已经被废弃了吗?谈谈你对此的看法。
204 0
|
缓存 监控 算法
内容服务锁优化实践
内容服务锁优化实践
92 0
|
设计模式 消息中间件 NoSQL
查漏补缺第二期(synchronized & 锁升级)
前言 目前正在出一个查漏补缺专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~ 本专题主要以Java语言为主, 好了, 废话不多说直接开整吧~ Q1 & 请说说对synchronized的理解 在Java中,关键字synchronized用于实现多线程之间的同步。它可以应用于方法或代码块,并确保在同一时间只有一个线程可以访问被同步的代码段.
|
存储 安全 Java
大白话讲解synchronized锁升级套路
synchronized锁是啥?锁其实就是一个对象,随便哪一个都可以,Java中所有的对象都是锁,换句话说,Java中所有对象都可以成为锁。 这次我们主要聊的是synchronized锁升级的套路
125 0
synchronized锁升级原理剖析 ✨ 每日积累
synchronized锁升级原理剖析 ✨ 每日积累
synchronized锁升级原理剖析 ✨ 每日积累
|
存储 安全 Java
小白也能看懂的锁升级过程和锁状态
小白也能看懂的锁升级过程和锁状态
258 0
小白也能看懂的锁升级过程和锁状态
|
SQL 监控 关系型数据库
死锁分析延续
可知上一篇【死锁分析】,又重新表达了一些图片,图画更了
152 0
死锁分析延续
|
安全 Java Windows
面试16解析-深挖锁(上)
题目:请分析一下Java锁机制的实现原理(主要是画Monitor示意图);Java锁有哪些种类,以及它们的区别?
317 0
面试16解析-深挖锁(上)