ReentrantLock 实现
ReentrantLock 实现:

我们主要看一下非公平锁的实现:
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
//cas 原子性操作,将state 状态改变为1
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());//返回true ,说明目前现在还没有线程进来,那么就将当前的线程标记为锁的线程
else
//否则的话,执行如下逻辑
acquire(1);
}
执行如下方法(包含了主要的3个方法): tryAcquire addWaiter acquireQueued
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
//非公平锁实现
return nonfairTryAcquire(acquires);
}
/**
* 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();
//获取当前state 的值这个值表示当前锁被重入的次数
int c = getState();
if (c == 0) {
//如果=0,表示当前锁还未被占用
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");
//标记state ,重入的次数
setState(nextc);
return true;
}
//表示线程未申请到锁
return false;
}
在线程未申请到锁的时候:会执行 addWaiter acquireQueued 这两个方法:
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
//预先处理下,解决性能问题
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
我们主要看一下如何将线程安全同步的加入到队列中: 如下典型的乐观锁的实现:cas +for 循环重试机制
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
完成了加入队列的操作后接下来就是 acquireQueued 操作了
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
//循环阻塞
for (;;) {
final Node p = node.predecessor();
//如果当前node 节点的上一个节点是head 以及state 状态=0 时候(有线程释放锁的时候)
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
//唯一出口
return interrupted;
}
//线程park 阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
ReentrantLock 实现的更多相关文章
- Java并发基础框架AbstractQueuedSynchronizer初探(ReentrantLock的实现分析)
AbstractQueuedSynchronizer是实现Java并发类库的一个基础框架,Java中的各种锁(RenentrantLock, ReentrantReadWriteLock)以及同步工具 ...
- 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析
前篇博客LZ已经分析了ReentrantLock的lock()实现过程,我们了解到lock实现机制有公平锁和非公平锁,两者的主要区别在于公平锁要按照CLH队列等待获取锁,而非公平锁无视CLH队列直接获 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之二lock方法分析
前一篇博客简单介绍了ReentrantLock的定义和与synchronized的区别,下面跟随LZ的笔记来扒扒ReentrantLock的lock方法.我们知道ReentrantLock有公平锁.非 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介
注:由于要介绍ReentrantLock的东西太多了,免得各位客官看累,所以分三篇博客来阐述.本篇博客介绍ReentrantLock基本内容,后两篇博客从源码级别分别阐述ReentrantLock的l ...
- java线程 公平锁 ReentrantLock(boolean fair)
一.公平锁 1.为什么有公平锁 CPU在调度线程的时候是在等待队列里随机挑选一个线程,由于这种随机性所以是无法保证线程先到先得的(synchronized控制的锁就是这种非公平锁).但这样就会产生饥饿 ...
- Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...
- 【JUC】JDK1.8源码分析之ReentrantLock(三)
一.前言 在分析了AbstractQueuedSynchronier源码后,接着分析ReentrantLock源码,其实在AbstractQueuedSynchronizer的分析中,已经提到过Ree ...
- Lock、ReentrantLock、synchronized、ReentrantReadWriteLock使用
先来看一段代码,实现如下打印效果: 1 2 A 3 4 B 5 6 C 7 8 D 9 10 E 11 12 F 13 14 G 15 16 H 17 18 I 19 20 J 21 22 K 23 ...
- java分析源码-ReentrantLock
一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...
随机推荐
- python守护进程
1.守护进程 [1]使用runner这个模块直接创建守护进程,非常方便. [2]运行方法:python xxx.py start|stop|restart [3]调用python xxx.py sto ...
- 学习MeteoInfo二次开发教程(十)
1.复制文件cloud_1009271330.000,I-01.pal 2.改: GridData cloud = aDataInfo.GetGridData(""); 为: Gr ...
- Python课程第四天作业
1.定义一个函数,该函数可以实现控制台输入,最终返回一个int类型的正整数 def chr_to_int(): user_input = input('请输您要转换的字符串:') if user_in ...
- 如何将composer设置为全局变量?
全局安装是将 Composer 安装到系统环境变量 PATH 所包含的路径下面,然后就能够在命令行窗口中直接执行 composer 命令了. Mac 或 Linux 系统: 打开命令行窗口并执行如下命 ...
- DLC 基本定律与规则2
逻辑函数的相等 布尔代数 9 个定律 三条规则 代入规则
- Android 开发 SharedPreferences数据会话类模板
简单的模板 public class SPDataSession { private static SPDataSession mSPDataSession; private SharedPrefer ...
- 小程序构建npm出现没有找到node_modules
以下转自:https://blog.csdn.net/zhangyabo_code/article/details/86162671 npm initnpm install --production ...
- 关于JWTtoken的管理问题
JWT简介: Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准.因为网络上有很多关于jwt的详细介绍了,所以我这里就不再赘述.但是JWT的大 ...
- windows文件名格式的中文+数字混合字符串排序
记录一下 [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] private static extern int StrCm ...
- MSMQ—确认队列和响应队列
一.MSMQ——消息的响应(响应队列) 如果需要从接收程序中获得比确认消息更多的信息(消息确认参考二),就可以使用响应队列.响应队列类似于一般队列,但原始发生程序吧该队列用作接收程序,原始接收 程序把 ...