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 的分析中,已经提到 ...
随机推荐
- 刘志梅 2017710101152《面向对象程序设计(java)》 第十周学习总结
实验十 泛型程序设计技术 实验时间 2018-11-1 1.实验目的与要求 (1)泛型程序设计:意味着编写的代码可以被很多不同类型的对象所重用.(ArrayList类可以聚集任何类型的对象) 如果在 ...
- redis集群报错:(error) CLUSTERDOWN Hash slot not served
百度上坑太多,如果你遇到搭建redis集群的时候出现这个错误在百度上找到解决办法基本上都是坑. 首先集群搭建完成后,你肯定去登陆redis进行测试 1.redis01/redis-cli -h &qu ...
- VMare Workstation 12 安装 AsteriskNow freePBX
一.准备工作 VMware 12 安装好的电脑 AsteriskNow iso文件 官网地址 https://www.asterisk.org/downloads 本人提供相关分享:https:// ...
- 为什么你需要少看垃圾博客以及如何在Python里精确地四舍五入
今天又有一个Python初学者被中文技术博客中的垃圾文章给误导了. 这位初学者的问题是: 在Python中,如何精确地进行浮点数的四舍五入,保留两位小数? 如果你在Google或者百度上搜索,你会发现 ...
- Java反射讲解
首先我们通过代码来看看发射的作用到底是什么. 1. 首先准备两个很简单的业务类 2. 非反射方式切换不同的业务方法调用 当需要从第一个业务方法切换到第二个业务方法的时候,使用非反射方式,必须修改代码, ...
- 如何利用Git生成pitch和打pitch
利用Git生成和应用patch 在程序员的日常开发与合作过程中,对于code的生成patch和打patch(应用patch)成为经常需要做的事情. 什么是patch?简单来讲,patch中存储的是你 ...
- HTML5 汉字转化为拼音,带读声,穷举多音字
1,没别的,像这种没有规则的转化,我们首先需要一个字典文件,字典文件的完整度,决定了转化的成功率与精确度 2,笔者收集了较为完整的字典文件,已上传到博客园,欢迎补充 => https://b ...
- Java学习随笔(1)--groovy爬虫
package com.fan import com.fission.source.httpclient.ApiLibraryimport com.fission.source.httpclient. ...
- MySql数据库时区异常,java.sql.SQLException: The server time zone value '?й???׼ʱ?' is unrecognized or represents more than one time zone.
JDBC访问MySql异常 Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException ...
- C# 字符串按 ASCII码 排序,注意其中的小坑
https://www.cnblogs.com/similar/p/6739293.html 在和银行做数据对接时,涉及到数据传输时的验签及加密.其中数据签名方案中就要求数据项根据属性名按 ASCII ...