- 持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情
可重入锁(递归锁)
- 解释一下什么是可重入:一个线程可以重复获取那把锁🔒。也就是第那种递归 调用,可以重复的执行当前方法。
那个类是那种可重入锁:
- ReentrantLock 这个类就是可重入的
- 还有那个关键字:synchronized 他也是可重入的 可重入有什么好处:提高代码的封装性
举个两个例子来看看
- 你在电影院 抢票 。我们在抢票时,两个人不能买同一个座位的票,点击下单的同时,他会锁住当前座位3分钟,在三分钟之类支付就行。对不对。这个时候我们就可以采用 ReentrantLock 来解决这个抢票。这里人就表示 线程。
- 第二个例子就是给大家展示一下一个线程不断的重入过程
第一个例子代码展示:
首先说一下这个例子我们可以用synchronized来实现。在这里我们采用ReentrantLock 来解决; 上代码:
/*******************************************************************************
* Package: com.song.boot.springstudy.thread.lock
* Type: ReentrantLockCinema
* Date: 2022-06-04 21:47
*
* Copyright (c) 2022 HUANENG GUICHENG TRUST CORP.,LTD All Rights Reserved.
*
* You may not use this file except in compliance with the License.
*******************************************************************************/
package com.song.boot.springstudy.thread.lock;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.ReentrantLock;
/**
* 功能描述:电影院 ReentrantLockCinema
* 可以提高代码的封装性
* @author Songxianyang
* @date 2022-06-04 21:47
*/
@Slf4j
public class ReentrantLockCinema {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
new Thread(() -> new ReentrantLockCinema().cinema(1)).start();
new Thread(() -> new ReentrantLockCinema().cinema(2)).start();
new Thread(() -> new ReentrantLockCinema().cinema(3)).start();
new Thread(() -> new ReentrantLockCinema().cinema(4)).start();
}
/**
* 代码的封装业务
*/
private void cinema(int i) {
lock.lock();
try {
// 具体的业务
System.out.println("具体的业务在try里面写-执行了哈哈哈" + i + "线程编号 " + Thread.currentThread().getName());
Thread.sleep(1000);
System.out.println("成功预定座位号:" + i +"祝您观看愉快!!");
System.out.println("-------------");
} catch (InterruptedException e) {
e.printStackTrace();
log.info("cinema: "+e);
} finally {
lock.unlock();
}
}
}
打印的结果为:
刚刚在写程序的发现了一个比较有意思的问题。分享一下给大家
不加:static
private ReentrantLock lock = new ReentrantLock();
/*******************************************************************************
* Package: com.song.boot.springstudy.thread.lock
* Type: ReentrantLockCinema
* Date: 2022-06-04 21:47
*
* Copyright (c) 2022 HUANENG GUICHENG TRUST CORP.,LTD All Rights Reserved.
*
* You may not use this file except in compliance with the License.
*******************************************************************************/
package com.song.boot.springstudy.thread.lock;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.ReentrantLock;
/**
* 功能描述:电影院 ReentrantLockCinema
* 可以提高代码的封装性
* @author Songxianyang
* @date 2022-06-04 21:47
*/
@Slf4j
public class ReentrantLockCinema {
private ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
new Thread(() -> new ReentrantLockCinema().cinema(1)).start();
new Thread(() -> new ReentrantLockCinema().cinema(2)).start();
new Thread(() -> new ReentrantLockCinema().cinema(3)).start();
new Thread(() -> new ReentrantLockCinema().cinema(4)).start();
}
/**
* 代码的封装业务
*/
private void cinema(int i) {
lock.lock();
try {
// 具体的业务
System.out.println("具体的业务在try里面写-执行了哈哈哈" + i + "线程编号 " + Thread.currentThread().getName());
Thread.sleep(1000);
System.out.println("成功预定座位号:" + i +"祝您观看愉快!!");
System.out.println("-------------");
} catch (InterruptedException e) {
e.printStackTrace();
log.info("cinema: "+e);
} finally {
lock.unlock();
}
}
}
- 有点意思 哈哈哈 是不是
分析:
static修饰变量,而且是对象的属性。你在操作多个对象的时候他是共享当前变量的副本。
不加关键字static,的时候。每一次线程进来都有一个新的副本。
所以当我在执行,main方法的时候 四个线程进来,不同的ReentrantLock副本。也就是说四个线程同时获得不同的锁。
我们获取锁的概念是:多个线程去竞争同一把锁。 从而解锁就就从第四个线程 递减这解锁。 这篇文章可以借鉴一下看看
记录一下刚刚写代码 所发生的问题(开心)
重入锁例子2
首先说一下这个方法
- getHoldCount:查询当前线程持有该锁的次数
代码
/*******************************************************************************
* Package: com.song.boot.springstudy.thread.lock
* Type: ReentrantLockTest
* Date: 2022-06-04 22:29
*
* Copyright (c) 2022 HUANENG GUICHENG TRUST CORP.,LTD All Rights Reserved.
*
* You may not use this file except in compliance with the License.
*******************************************************************************/
package com.song.boot.springstudy.thread.lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 功能描述: 一个线程不断的去重入的过程 也是递归的过程
*
* @author Songxianyang
* @date 2022-06-04 22:29
*/
public class ReentrantLockTest {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
System.out.println(lock.getHoldCount());
lock.lock();
System.out.println(lock.getHoldCount());
lock.lock();
System.out.println(lock.getHoldCount());
lock.lock();
System.out.println(lock.getHoldCount());
System.out.println("-----------");
lock.unlock();
System.out.println(lock.getHoldCount());
lock.unlock();
System.out.println(lock.getHoldCount());
lock.unlock();
System.out.println(lock.getHoldCount());
}
}
效果图
主线程不断的递归 不断的重入
0 没有获取锁所以打印0
1 获取第一把锁所以打1
2 获取第2把锁所以打印0
3
-----------
2 解锁其中一个后 打印2
1
0 解锁完了打印0