当前位置:网站首页>How ReentrantLock works
How ReentrantLock works
2022-08-02 02:45:00 【Season of monsoon die out】
- 一般是通过一个内部类Sync继承 AQS
- 将同步器所有调用都映射到Sync对应的方法

- 阻塞等待队列
- 共享/独占
- 公平/非公平
- 可重入
- 允许中断
- state表示资源的可用状态
- State三种访问方式:
- getState()
- setState()
- compareAndSetState()
- Exclusive-独占,只有一个线程能执行,如ReentrantLock
- Share-共享,多个线程可以同时执行,如Semaphore/CountDownLatch
- 同步等待队列: 主要用于维护获取锁失败时入队的线程
- 条件等待队列: 调用await()的时候会释放锁,然后线程会加入到条件队列,调用signal()唤醒的时候会把条件队列中的线程节点移动到同步队列中,等待再次获得锁
ReentrantLock
- 可中断
- 可以设置超时时间
- 可以设置为公平锁
- 支持多个条件变量
- 与 synchronized 一样,都支持可重入

synchronized和ReentrantLock的区别:
- synchronized关键字,是JVM层次的锁实现,ReentrantLock是类,是JDKHierarchy is based onAQS的锁实现;Both are reentrant exclusive locks.
- synchronized的锁状态是无法在代码中直接判断的,但是ReentrantLock可以通过 ReentrantLock#isLocked判断;
- synchronized自动加解锁,ReentrantLockTo unlock manually,Its operation is more flexible.
- synchronized是非公平锁,ReentrantLock是可以是公平也可以是非公平的;ReentrantLockTo ensure fairness also introduces additional overhead,导致吞吐量下降,慎用.
- synchronized是不可以被中断的,而ReentrantLock#lockInterruptibly方法是可以被中断的;
- 在发生异常时synchronized会自动释放锁,而ReentrantLock需要开发者在finally块中显示释放锁;
- ReentrantLock获取锁的形式有多种:如立即返回是否成功的tryLock(),and waiting fingersTimed acquisition,更加灵活;
- synchronized在特定的情况下对于已经在等待的线程是后来的线程先获得锁(回顾一下sychronized的唤醒策略),而ReentrantLockFor threads that are already waiting, it is the first-come thread先获得锁;
- in low competition situationssynchronized的性能优于ReentrantLock.在高并发下,synchronized操作monitorUser mode involving threads、内核态的切换,性能不如ReentrantLock.
ReentrantLock的使用
同步执行,类似于synchronized
private static int sum = 0;
private static Lock lock = new ReentrantLock();
//private static TulingLock lock = new TulingLock();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(()->{
//加锁
lock.lock();
try {
// 临界区代码
// TODO 业务逻辑:读写操作不能保证线程安全
for (int j = 0; j < 10000; j++) {
sum++;
}
} finally {
// 解锁
lock.unlock();
}
});
thread.start();
}
Thread.sleep(2000);
System.out.println(sum);
}可重入
public static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
method1();
}
public static void method1() {
lock.lock();
try {
log.debug("execute method1");
method2();
} finally {
lock.unlock();
}
}
public static void method2() {
lock.lock();
try {
log.debug("execute method2");
method3();
} finally {
lock.unlock();
}
}
public static void method3() {
lock.lock();
try {
log.debug("execute method3");
} finally {
lock.unlock();
}
}可中断
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
log.debug("t1启动...");
try {
lock.lockInterruptibly();
try {
log.debug("t1获得了锁");
} finally {
lock.unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
log.debug("t1等锁的过程中被中断");
}
}, "t1");
lock.lock();
try {
log.debug("main线程获得了锁");
t1.start();
//先让线程t1执行
Thread.sleep(1000);
t1.interrupt();
log.debug("线程t1执行中断");
} finally {
lock.unlock();
}锁超时
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
log.debug("t1启动...");
// 注意: 即使是设置的公平锁,此方法也会立即返回获取锁成功或失败,公平策略不生效
// if (!lock.tryLock()) {
// log.debug("t1获取锁失败,立即返回false");
// return;
// }
//超时
try {
if (!lock.tryLock(1, TimeUnit.SECONDS)) {
log.debug("等待 1s 后获取锁失败,返回");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
try {
log.debug("t1获得了锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
try {
log.debug("main线程获得了锁");
t1.start();
//先让线程t1执行
Thread.sleep(2000);
} finally {
lock.unlock();
}公平锁
//ReentrantLock lock = new ReentrantLock(true); //公平锁
ReentrantLock lock = new ReentrantLock(); //非公平锁
for (int i = 0; i < 500; i++) {
new Thread(() -> {
lock.lock();
try {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug(Thread.currentThread().getName() + " running...");
} finally {
lock.unlock();
}
}, "t" + i).start();
}
// 1s 之后去争抢锁
Thread.sleep(1000);
for (int i = 0; i < 500; i++) {
new Thread(() -> {
lock.lock();
try {
log.debug(Thread.currentThread().getName() + " running...");
} finally {
lock.unlock();
}
}, "强行插入" + i).start();
}条件变量
private static ReentrantLock lock = new ReentrantLock();
private static Condition cigCon = lock.newCondition();
private static Condition takeCon = lock.newCondition();
private static boolean hashcig = false;
private static boolean hastakeout = false;
//送烟
public void cigratee(){
lock.lock();
try {
while(!hashcig){
try {
log.debug("没有烟,歇一会");
cigCon.await();
}catch (Exception e){
e.printStackTrace();
}
}
log.debug("有烟了,干活");
}finally {
lock.unlock();
}
}
//送外卖
public void takeout(){
lock.lock();
try {
while(!hastakeout){
try {
log.debug("没有饭,歇一会");
takeCon.await();
}catch (Exception e){
e.printStackTrace();
}
}
log.debug("有饭了,干活");
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLockDemo6 test = new ReentrantLockDemo6();
new Thread(() ->{
test.cigratee();
}).start();
new Thread(() -> {
test.takeout();
}).start();
new Thread(() ->{
lock.lock();
try {
hashcig = true;
log.debug("唤醒送烟的等待线程");
cigCon.signal();
}finally {
lock.unlock();
}
},"t1").start();
new Thread(() ->{
lock.lock();
try {
hastakeout = true;
log.debug("唤醒送饭的等待线程");
takeCon.signal();
}finally {
lock.unlock();
}
},"t2").start();
}ReentrantLock源码
加锁:
- CAS加锁,Set the reentrant thread as the current thread on success.reentrancy number plus1.
- If the lock fails, the thread is put into a waiting queue of a doubly linked list,并调用unsafe.park()挂起线程.
解锁:
- Set the reentrant thread directly tonull,将state还原为0.
- 调用unsafe.park()Arouse a thread in the waiting queue to compete for the lock.
边栏推荐
- Rasa 3 x learning series - Rasa - 4873 dispatcher Issues. Utter_message study notes
- Install mysql using docker
- Qt自定义控件和模板分享
- 使用docker安装mysql
- Pinduoduo leverages the consumer expo to promote the upgrading of domestic agricultural products brands and keep pace with international high-quality agricultural products
- 微信小程序异步回调函数恶梦和解决办法
- 局部敏感哈希:如何在常数时间内搜索Embedding最近邻
- qt点云配准软件
- 20. 用两个栈实现队列
- Moonbeam and Project integration of the Galaxy, bring brand-new user experience for the community
猜你喜欢

搭建zabbix监控及邮件报警(超详细教学)

The failure to create a role in Dahua Westward Journey has been solved

pyqt上手体验

The principle and code implementation of intelligent follower robot in the actual combat of innovative projects

【web】Understanding Cookie and Session Mechanism

ros多客户端请求服务

【每日一道LeetCode】——1. 两数之和

2022牛客多校四_G M

记一个gorm初始化的坑

【web】理解 Cookie 和 Session 机制
随机推荐
cadence landscape bindkey
mockjs生成假数据的基本使用
Entry name 'org/apache/commons/codec/language/bm/gen_approx_greeklatin.txt' collided
使用DBeaver进行mysql数据备份与恢复
很有意思的经历,很有意思的项目--文件夹对比工具
忽晴忽雨
Unable to log in to the Westward Journey
How engineers treat open source
TKU remembers a single-point QPS optimization (I wish ITEYE is finally back)
ros多客户端请求服务
IPFS部署及文件上传(golang)
PHP live source code to achieve simple barrage effect related code
60 Feature Engineering Operations: Using Custom Aggregate Functions【Favorites】
Lombok
Power button 1374. Generate each character string is an odd number
2022 Henan Youth Training League Game (3)
51. 数字排列
【CNN记录】tensorflow slice和strided_slice
BI - SQL 丨 WHILE
Good News | AR opens a new model for the textile industry, and ALVA Systems wins another award!