博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ReentrantLock源码---JDK1.8
阅读量:4653 次
发布时间:2019-06-09

本文共 3968 字,大约阅读时间需要 13 分钟。

可重入锁实现:给每一个锁关联一个获取计数值和一个所有者线程 非公平锁:抢占式,直接尝试修改state,获取锁 公平锁:先检查同步等待队列是否有等待的线程,先来先得
//构造函数,默认是非公平锁    public ReentrantLock() {        sync = new NonfairSync();    } //指定策略    public ReentrantLock(boolean fair) {        sync = fair ? new FairSync() : new NonfairSync();    }

 

先看看Sync这个类,继承自AQS:(因为默认是非公平模式,所以这里直接实现了非公平模式下的尝试获取锁)

//非公平模式尝试获取锁        final boolean nonfairTryAcquire(int acquires) {            final Thread current = Thread.currentThread();            int c = getState();            if (c == 0) {                //c=0,说明当前没有线程获取锁,CAS尝试设置state,获取锁                if (compareAndSetState(0, acquires)) {                    //抢占成功,将当前线程设置为独占模式                    setExclusiveOwnerThread(current);                    return true;                }            }            //到这里,说明锁已经被持有,检查持有锁的线程是否为当前线程            else if (current == getExclusiveOwnerThread()) {                //如果是,累加重入次数                int nextc = c + acquires;                //小于0 ,超过int的最大值了                if (nextc < 0) // overflow                    throw new Error("Maximum lock count exceeded");               //设置state                setState(nextc);                return true;            }            //如果锁已经被抢占,并且持有线程不是当前线程,返回false。            return false;        }        //尝试释放锁        protected final boolean tryRelease(int releases) {            //释放时,需要减去重入次数            int c = getState() - releases;            //如果当前线程不是独占模式所有者,抛异常            if (Thread.currentThread() != getExclusiveOwnerThread())                throw new IllegalMonitorStateException();            boolean free = false;            if (c == 0) {                //c=0,释放完毕,                free = true;                //解除所有者关系                setExclusiveOwnerThread(null);            }            //设置重入次数            setState(c);            return free;        }

 

看看子类NonfairSync 非公平锁的实现:
final void lock() {            //非公平锁,抢占模式,CAS直接尝试设置state,获取锁。            if (compareAndSetState(0, 1))                //获取成功,将当前线程设置为所有者                setExclusiveOwnerThread(Thread.currentThread());            else                //CAS失败,在独占模式下请求。                acquire(1);        }        //非公平锁,尝试请求        protected final boolean tryAcquire(int acquires) {            //直接调用父类方法            return nonfairTryAcquire(acquires);        }

再看看子类FairSync 公平锁的实现:

 

final void lock() {            acquire(1);        }        /**         * Fair version of tryAcquire.  Don't grant access unless         * recursive call or no waiters or is first.         */        //公平锁的tryAcquire()。        //只有在递归(重入)或者同步队列中没有其他线程        //或者当前线程是等待队列中的第一个线程时,才允许访问。        protected final boolean tryAcquire(int acquires) {            final Thread current = Thread.currentThread();            int c = getState();            if (c == 0) {                //如果c=0,说明锁没有被持有,需要检查同步等待队列中                //是否有其他线程,如果没有,尝试设置state                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");                //设置state                setState(nextc);                return true;            }            return false;        }

 

整理一下大概逻辑:

 

加锁操作:

非公平:
1.直接CAS抢占设置state,如果成功,获取锁成功。
2.如果获取失败,需要检查锁是否被其他线程持有
3.如果没有其他线程持有锁,会以CAS的方式尝试获取锁,
,如果成功,获取锁成功。
4.如果有其他线程持有锁,会检查一下持有锁的线程是否为当前线程
如果是,累加重入次数。
公平:
1.会先检查锁是否被其他线程持有,并且检查同步等待队列里有没有其他线程
2.如果没有其他线程持有锁,且同步等待队列里面没有其他线程,会以CAS的方式
尝试获取锁,CAS成功,获取锁成功。
3.如果有其他线程持有锁,检查是否为当前线程,如果是
累加重入次数,获取锁成功。

解锁操作:
1.当前线程先将重入次数减1,如果结果为0,将当前同步器的线程
信息清空,并唤醒同步等待队列中队列头的等待线程
2.如果重入次数减1后结果不为0(说明当前线程还持有当前锁),方法结束

 

转载于:https://www.cnblogs.com/emoji1213/p/7801081.html

你可能感兴趣的文章
UVa 541 Error Correction
查看>>
读APUE分析散列表的使用
查看>>
解决文件上传时,服务器中中文文件名乱码问题
查看>>
XPATH如何选择,t选取,包含某一属性的节点, 不包含某一个属性的节点?
查看>>
hihoCoder #1110 Regular Expression
查看>>
jquery选中checkbox多选项并添加到文本框中
查看>>
视频会议软件能否采用免费的商业模式
查看>>
Gridview用法大总结(蛇年珍藏版)
查看>>
CI框架后台添加左侧导航栏出现的一系列问题
查看>>
cocos2d-js 运行动画
查看>>
1.基础知识
查看>>
[NOI2018]你的名字
查看>>
关于mysql中select * for update锁表与Deadlock found when trying to get lock; try restarting transaction...
查看>>
[uva 1350]数位dp+二分
查看>>
使用Gitosis搭建Git服务器
查看>>
445port入侵具体解释
查看>>
具体解释Android中AsyncTask的使用
查看>>
sed中求公共前缀
查看>>
Java模式(适配器模式)
查看>>
优雅到骨子里的Requests
查看>>