IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> ReentrantLock分析 -> 正文阅读

[Java知识库]ReentrantLock分析

一、介绍

ReentrantLock是JUC包下的一个类,他是可重入锁,同一个线程可以对资源重复加锁。ReentrantLock而且支持公平和非公平的模式,公平模式下按等待时间来排队获取。也就是一个FIFO队列
(synchronized 是隐式支持重入的)

二、源码分析

ReentrantLock 内部是通过组合的方式,实现自定义的同步同步器

abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = -5179523762034025860L;

 /**
 * 非公平锁
 */
 static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
    
    
    /**
    * 公平锁
    */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

       	// 省略部分代码
        }
    }


/**
* 构造器中构造自定义同步器
* 默认是非公平锁
*/
public ReentrantLock() {
    
        sync = new NonfairSync();
}
 

public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
 }
    
 

通过源码可以知道ReentrantLock 默认是非公平模式。

2.1 非公平锁-加锁

     
final void lock() {
    // 尝试加锁
    // AQS内部有一个 state来表示资源的占用情况
    // 0表示未被占用
    if (compareAndSetState(0, 1))
        // 设置为当前线程
        setExclusiveOwnerThread(Thread.currentThread());
    else
        // 内部进入阻塞 (内部也有可重入的逻辑)
        acquire(1);
}

核心方法,非公平的方式获取资源

 /**
         * Performs non-fair tryLock.  tryAcquire is implemented in
         * subclasses, but both need nonfair try for trylock method.
         * 以非公平的方式 获取资源
         */
        final boolean nonfairTryAcquire(int acquires) {
            // 获取当前线程
            final Thread current = Thread.currentThread();

            // 获取当前资源状态 0 初始 1资源被占用
            int c = getState();

            // 未被占用
            if (c == 0) {
                // cas方式设置设置占有资源
                if (compareAndSetState(0, acquires)) {
                    // 设置当前线程
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 如果是当前线程,重入功能
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            // 未获取到资源
            return false;
        }

  • 主要流程就是
    • 判断资源状态
    • CAS更新
    • 锁重入

2.2 释放锁

  /**
         * 进行锁的释放 当 state资源为0
         * 表示锁已经被释放了
         * @param releases
         * @return
         */
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            // 非当前线程 无法释放 抛出异常
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

2.3 公平锁加锁

protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                // 即加入了同步队列中当前节点是否有前驱节点的判断,如果该 方法返回true,
                //  则表示有线程比当前线程更早地请求获取锁
                // 其实就是判断是否 有在等待的(除非自己),如果在等待,不好意思没机会,你慢慢在
                // 后续加入队列后,慢慢等
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
  • 公平锁的最大区别是多了一个hasQueuedPredecessors方法,判断是否在等待队列中

三、小结

  • ReentrantLock默认是非公平锁,可以抢占获取锁
  • 公平锁的模式 按请求顺序阻塞获取锁 FIFO获取

四、参考

《Java并发编程的艺术》

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 21:59:56  更:2022-03-11 22:04:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/2 2:31:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码