当前位置:网站首页>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.
边栏推荐
- FOFAHUB usage test
- Oracle19c安装图文教程
- 2022.8.1-----leetcode.1374
- 项目场景 with ERRTYPE = cudaError CUDA failure 999 unknown error
- ALCCIKERS Shane 20191114
- qt点云配准软件
- The principle and code implementation of intelligent follower robot in the actual combat of innovative projects
- 第10章_索引优化与查询优化
- 数值积分方法:欧拉积分、中点积分和龙格-库塔法积分
- 简单的页面跳转活动
猜你喜欢

Outsourcing worked for three years, it was abolished...

Analysis of the status quo of digital transformation of manufacturing enterprises

The state status is displayed incorrectly after the openGauss switch

AWR analysis report questions for help: How can SQL be optimized from what aspects?

【web】理解 Cookie 和 Session 机制

MySQL索引优化实战

svm.SVC应用实践1--乳腺癌检测

字典常用方法

Flask入门学习教程

analog IC layout
随机推荐
线程的不同状态
使用docker安装mysql
qt点云配准软件
nacos startup error, the database has been configured, stand-alone startup
【LeetCode】102.二叉树的层序遍历
永磁同步电机36问(三)——SVPWM代码实现
【web】Understanding Cookie and Session Mechanism
IMU预积分的简单理解
第10章_索引优化与查询优化
Ringtone 1161. Maximum In-Layer Elements and
What to study after the PMP exam?The soft exam ahead is waiting for you~
树链剖分-
1688API
2022牛客多校四_G M
记一个gorm初始化的坑
CASE2023
2022年NPDP考完多久出成绩?怎么查询?
The first time I wrote a programming interview question for Niu Ke: input a string and return the letter with the most occurrences of the string
yaml
Unable to log in to the Westward Journey