ReentrantLock可重入锁的理解和源码简单分析
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; /**
* @author admin
* @date 2018/1/16 12:16
* ReentrantLock 可重入锁:
* 1、启动两个线程,线程A获取锁,然后执行;同时线程B进来后,一直阻塞,直到线程A释放锁之后,线程B才接着执行
*/
public class ReentrantLockTest {
ReentrantLock lock = new ReentrantLock(); public void reentrantLockRun1(String threadName) {
System.out.println(threadName + "进入");
lock.lock();
System.out.println(threadName + "方法被锁");
try {
System.out.println(threadName + "方法执行");
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.out.println(threadName + "锁被释放");
}
} public static void main(String[] args) {
ReentrantLockTest rltest = new ReentrantLockTest();
Thread thread = new Thread() {
public void run() {
rltest.reentrantLockRun1("线程A");
}
};
thread.start(); Thread thread2 = new Thread() {
public void run() {
rltest.reentrantLockRun1("线程B");
}
};
thread2.start();
}
} 运行结果:
线程A进入
线程A方法被锁
线程A方法执行
线程B进入
线程A锁被释放
线程B方法被锁
线程B方法执行
线程B锁被释放
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; /**
* @author admin
* @date 2018/1/16 12:16
* ReentrantLock 可重入锁:
* 1、启动两个线程,线程A获取锁,然后执行,不释放锁,接着线程A再调用reentrantLockRun2,不需要阻塞,接着执行,最后释放锁;说明同一个线程对ReentrantLock可重复获取
* 2、线程B在这个过程中一直阻塞,等到线程A把所有的锁释放完之后,再获取锁,执行方法,最后释放锁
*/
public class ReentrantLockTest2 {
ReentrantLock lock = new ReentrantLock(); public ReentrantLock reentrantLockRun1(String threadName) {
System.out.println(threadName + "进入");
lock.lock();
System.out.println(threadName + "方法被锁");
try {
System.out.println(threadName + "方法执行");
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return lock;
} public ReentrantLock reentrantLockRun2(String threadName) {
System.out.println(threadName + "进入");
lock.lock();
System.out.println(threadName + "方法被锁");
try {
System.out.println(threadName + "方法执行");
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return lock;
} public static void main(String[] args) {
ReentrantLockTest2 rltest = new ReentrantLockTest2();
Thread thread = new Thread() {
public void run() {
ReentrantLock lock1 = rltest.reentrantLockRun1("线程A");
ReentrantLock lock2 = rltest.reentrantLockRun2("线程A2");
lock1.unlock();
System.out.println("线程A释放锁");
lock2.unlock();
System.out.println("线程A2释放锁"); }
};
thread.start(); Thread thread2 = new Thread() {
public void run() {
ReentrantLock lock = rltest.reentrantLockRun1("线程B");
lock.unlock();
System.out.println("线程B释放锁"); }
};
thread2.start();
}
} 运行结果:
线程A进入
线程A方法被锁
线程A方法执行
线程B进入
线程A2进入
线程A2方法被锁
线程A2方法执行
线程A释放锁
线程A2释放锁
线程B方法被锁
线程B方法执行
线程B释放锁
根据源码发现:维护了这个可见性变量state ;同一个线程对可重入锁体现用state标记作累加,int nextc = c + acquires;
private volatile int state;
public void lock() {
sync.lock();
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
} // 判断是不是第一次获取锁,如果是操作state=1;否则判断是不是同一个线程如果是state+1,如果不是同一个线程直接返回false
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
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;
}
}
// 大概就是用一个链表来维护等待线程
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
ReentrantLock可重入锁的理解和源码简单分析的更多相关文章
- ReenTrantLock可重入锁(和synchronized的区别)总结
ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...
- ReenTrantLock可重入锁和synchronized的区别
ReenTrantLock可重入锁和synchronized的区别 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也是可重入 ...
- JUC 一 ReentrantLock 可重入锁
java.util.concurrent.locks ReentrantLock即可重入锁,实现了Lock和Serializable接口 ReentrantLock和synchronized都是可重入 ...
- ReentrantLock——可重入锁的实现原理
一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQueuedSynchronizer的简单原理,然后通过分析ReentrantLock的lo ...
- java ReentrantLock可重入锁功能
1.可重入锁是可以中断的,如果发生了死锁,可以中断程序 //如下程序出现死锁,不去kill jvm无法解决死锁 public class Uninterruptible { public static ...
- 40 多线程(十二)——ReentrantLock 可重入锁
我们使用的synchronized加的锁是可以延续使用的,如下: public void test() { //第一次获得锁 synchronized(this) { while(true) { // ...
- ReentrantLock可重入锁、公平锁非公平锁区别与实现原理
ReentrantLock是lock接口的一个实现类,里面实现了可重入锁和公平锁非公平锁 ReentrantLock公平锁和不公平锁实现原理 公平锁会获取锁时会判断阻塞队列里是否有线程再等待,若有获取 ...
- ReentrantLock可重入锁——源码详解
开始这篇博客之前,博主默认大家都是看过AQS源码的~什么居然没看过猛戳下方 全网最详细的AbstractQueuedSynchronizer(AQS)源码剖析(一)AQS基础 全网最详细的Abstra ...
- ReentrantLock可重入锁的使用场景(转)
摘要 从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些. 场景1:如果发现该操作已经在执行中则不再执行(有状态执行) a.用在定时任务时,如果任务执行时间可能超过下次 ...
随机推荐
- NodeJS Stream流
NodeJS Stream流 流数据在网络通信中至关重要,nodeJS用Stream提供了一个抽象接口,node中有很多对象实现了这个接口,提供统一的操作体验 基本流类型 NodeJS中,Stream ...
- JS_高程7.函数表达式(1)
定义函数的两种常见的方法: 1 . 函数声明 2. 函数表达式 # 差异 (1)函数声明 ,具有函数声明提升的特征. (2)函数声明的函数的name属性为函数的名称:使用函数表达式定义的函数在ES5中 ...
- ssh远程登陆看不到用户名和主机名
使用secure crt远程登陆,发现看不到用户名和主机名,如下图所示 解决方法 sudo vim /etc/passwd root:x:::root:/root:/bin/bash sshd:x:: ...
- Siamese网络
1. 对比损失函数(Contrastive Loss function) 孪生架构的目的不是对输入图像进行分类,而是区分它们.因此,分类损失函数(如交叉熵)不是最合适的选择,这种架构更适合 ...
- DBS:TestSystem
ylbtech-DBS:TestSystem A, 返回顶部 2. -- ================================= -- 类别表 -- ================= ...
- python读取excel(xlrd)
一.安装xlrd模块: 1.mac下打开终端输入命令: pip install xlrd 2.验证安装是否成功: 在mac终端输入 python 进入python环境 然后输入 import xl ...
- PHP判断一个JSON对象是否含有某一个属性的方法
property_exists比如:var json={"code":400,"msg":"User Err"} var rest=prop ...
- Windows下python3生成UTF8的CSV文件和sha256sum踩坑记录
CSV的坑 在Ubuntu下是简单的写入完事 import csv ... with open(filename, 'w') as output: f = csv.writer(output) f.w ...
- SuperObject生成示例
var jo,jEntity,jSubEntity: ISuperObject; jaOrder,jaEntity,jaSubEntity: ISuperObject; i,j,entityCount ...
- Rabbit五种消息队列学习(一) – 总述
RabbitMQ支持五种消息传递类型,分别如下图所示: 上图中显示6中消息队列分别为: 1.简单队列 一个生产者将消息放到队列中,一个消费者监听队列 2.工作队列(Work queues) 一个生产者 ...