当前位置:网站首页>[interview: concurrent Article 22 multithreading: reentrantlock]
[interview: concurrent Article 22 multithreading: reentrantlock]
2022-07-23 19:49:00 【I cream】
【 interview : Concurrent articles 22 Multithreading :ReentrantLock】
00. Preface
If you have any questions, please point out , thank .
01. Introduce
RennttrantLock Also lock and synchronized It also has the function of locking synchronous code blocks , But and synchronized There are still many differences .
RennttrantLock yes java.util.concurrent(juc) Next class , be relative to synchronized It has the following characteristics :
1. You can interrupt being in BLOCKED Other threads in state
2. You can set it to BLOCKED Thread timeout of state , If you exceed this time, give up fighting for the lock
3. Can be set to fair lock , Threads acquire locks according to first in first out
4. Support multiple conditional variables , This means For waiting areas We can have multiple When the call lock of different objects is in the waiting state, the waiting area is different , about synchronized Lock said There is only one waiting area WaitSet
And synchronized equally Both support lock reentry , That is, you can get your internal lock again
02. Basic grammar
ReentrantLock lock = new ReentrantLock();
lock.lock();
try{
// lock.lock();
// A critical region
}finally{
// Release the lock
lock.unlock();
}
Be careful :lock.lock(); Can be placed in try outside , It can also be placed in try Inside , Last in finally Need to be lock.unlock(); Release the lock
03. Lockable reentrant
Example
public class TestInterKCR {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
lock.lock();
try {
System.out.println("enter main");
m1();
}finally {
lock.unlock();
}
}
private static void m1(){
lock.lock();
try {
System.out.println("enter m1");
m2();
}finally {
lock.unlock();
}
}
private static void m2(){
lock.lock();
try {
System.out.println("enter m2");
}finally {
lock.unlock();
}
}
}
result
enter main
enter m1
enter m2
explain
You can see that your internal lock can be called , There was no deadlock , It means that you can lock and re-enter
04. Can interrupt
Introduce
Let's first clarify a concept , What is said here can be interrupted That's right A thread that has obtained a lock t1 And a thread in a blocked state t2( because t1 The lock has been acquired ), We can in other threads hold t2 Thread interrupt Make it Jump out of the blocking state Run other parts of the code .
synchronized Why not interrupt
Example
public class TestInterSync {
private static String a = "s";
public static void main(String[] args) {
Thread t1 = new Thread(()->{
System.out.println("t1 Attempt to acquire lock ");
synchronized (a){
System.out.println("t1 Get lock ");
boolean interrupted = Thread.currentThread().isInterrupted();
if (interrupted){
System.out.println("t1 Be interrupted ");
}
}
});
Thread t2 = new Thread(()->{
System.out.println("t2 Attempt to acquire lock ");
synchronized (a){
System.out.println("t2 Get lock ");
while (true){
}
}
});
t2.start();
Sleeper.sleep(0.5);
t1.start();
Sleeper.sleep(0.5);
System.out.println(" Interrupt the waiting lock t1 Threads ");
t1.interrupt();
}
}
result
The program is not over :
t2 Attempt to acquire lock
t2 Get lock
t1 Attempt to acquire lock
Interrupt the waiting lock t1 Threads
explain
We found that the program did not end , our t2 The thread program obtains the lock first and does not release the lock , Lead to t1 Thread blocking , Now we interrupt in the main thread t1 Threads But I found it impossible to interrupt
lock Can the method be interrupted ?
Example
public class TestInterReenY {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(()->{
System.out.println("t1 Attempt to acquire lock ");
lock.lock();
try {
System.out.println("t1 Get lock ");
}finally {
lock.unlock();
}
});
Thread t2 = new Thread(()->{
System.out.println("t2 Attempt to acquire lock ");
lock.lock();
try {
System.out.println("t2 Get lock ");
Sleeper.sleep(2);
}finally {
}
});
t2.start();
Sleeper.sleep(0.5);
t1.start();
Sleeper.sleep(0.5);
System.out.println(" Interrupt the waiting lock t1 Threads ");
t1.interrupt();
}
}
result
The program is not over :
t2 Attempt to acquire lock
t2 Get lock
t1 Attempt to acquire lock
Interrupt the waiting lock t1 Threads
explain
We found that lock Method still cannot interrupt a blocked thread , Then what should we use , The answer is lockInterruptibly Method
lockInterruptibly Method
Example
public class TestInterReen {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(()->{
try {
System.out.println("t1 Attempt to acquire lock ");
lock.lockInterruptibly();
} catch (InterruptedException e) {
System.out.println("t1 Be interrupted ");
return;
}
try {
System.out.println("t1 Get lock ");
}finally {
lock.unlock();
}
});
Thread t2 = new Thread(()->{
try {
System.out.println("t2 Attempt to acquire lock ");
lock.lockInterruptibly();
} catch (InterruptedException e) {
System.out.println("t2 Be interrupted ");
return;
}
try {
System.out.println("t2 Get lock ");
Sleeper.sleep(2);
}finally {
}
});
t2.start();
Sleeper.sleep(0.5);
t1.start();
Sleeper.sleep(0.5);
System.out.println(" Interrupt the waiting lock t1 Threads ");
t1.interrupt();
}
}
result
Program end :
t2 Attempt to acquire lock
t2 Get lock
t1 Attempt to acquire lock
Interrupt the waiting lock t1 Threads
t1 Be interrupted
explain
You can see that we use lockInterruptibly Method can be implemented Interrupt the blocked thread
05. Lock timeout
Introduce
Lock timeout refers to , Once the lock is occupied by other threads If no timeout is specified Then this thread will directly jump out of the blocking state Not competing , If a timeout is specified be Blocked during timeout Timeout exceeded Then jump out of the blocking state .
Example : Endless
@Slf4j(topic = "c.TestInterCS")
public class TestInterCS {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(()->{
log.debug("t1 Attempt to acquire lock ");
if (!lock.tryLock()){
log.debug("t1 Can't get lock ");
return;
}
try {
log.debug("t1 Get lock ");
}finally {
}
},"t1");
Thread t2 = new Thread(()->{
log.debug("t2 Attempt to acquire lock ");
if (!lock.tryLock()){
log.debug("t2 Can't get lock ");
return;
}
try {
log.debug(" Get lock ");
}finally {
lock.unlock();
}
},"t2");
t1.start();
Sleeper.sleep(1);
t2.start();
}
}
result
00:40:27.595 c.TestInterCS [t1] - t1 Attempt to acquire lock
00:40:27.597 c.TestInterCS [t1] - t1 Get lock
00:40:28.600 c.TestInterCS [t2] - t2 Attempt to acquire lock
00:40:28.600 c.TestInterCS [t2] - t2 Can't get lock
explain
It can be seen that t1 The thread acquires the lock and does not release ,t2 The thread has been blocked , We use it tryLock Method And no timeout is specified That is, once you find out t2 Thread is blocked lock.tryLock() return false, We execute other code
Example : Time limited
@Slf4j(topic = "c.TestInterCS")
public class TestInterCS {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(()->{
log.debug("t1 Attempt to acquire lock ");
try {
if (!lock.tryLock(2, TimeUnit.SECONDS)){
log.debug("t1 Can't get lock ");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
log.debug("t1 Get lock ");
}finally {
}
},"t1");
Thread t2 = new Thread(()->{
log.debug("t2 Attempt to acquire lock ");
if (!lock.tryLock()){
log.debug("t2 Can't get lock ");
return;
}
try {
log.debug(" Get lock ");
}finally {
lock.unlock();
}
},"t2");
t1.start();
Sleeper.sleep(1);
t2.start();
}
}
result
00:44:46.180 c.TestInterCS [t1] - t1 Attempt to acquire lock
00:44:46.183 c.TestInterCS [t1] - t1 Get lock
00:44:47.183 c.TestInterCS [t2] - t2 Attempt to acquire lock
00:44:47.183 c.TestInterCS [t2] - t2 Can't get lock
explain
We give tryLock Method specifies the time as 2s, But because t1 The thread never releases the lock , So the result lock.tryLock() Still back false, We make logical judgments , Execute other code
The dining problem of philosophers
Introduce
Before, we introduced the dining problem of philosophers , We used The sequential locking method solves the problem of deadlock , But then there was hunger , This time we use lock timeout to solve the problem of hunger
Code
@Slf4j(topic = "c.Test23")
public class Test23 {
public static void main(String[] args) {
Chopstick c1 = new Chopstick("1");
Chopstick c2 = new Chopstick("2");
Chopstick c3 = new Chopstick("3");
Chopstick c4 = new Chopstick("4");
Chopstick c5 = new Chopstick("5");
new Philosopher(" Socrates ", c1, c2).start();
new Philosopher(" Plato ", c2, c3).start();
new Philosopher(" Aristotle ", c3, c4).start();
new Philosopher(" Heraclitus ", c4, c5).start();
new Philosopher(" Archimedes ", c5, c1).start();
}
}
@Slf4j(topic = "c.Philosopher")
class Philosopher extends Thread {
Chopstick left;
Chopstick right;
public Philosopher(String name, Chopstick left, Chopstick right) {
super(name);
this.left = left;
this.right = right;
}
@Override
public void run() {
while (true) {
// Try to get left chopsticks
if(left.tryLock()) {
try {
// Try to get the right chopsticks
if(right.tryLock()) {
try {
eat();
} finally {
right.unlock();
}
}
} finally {
left.unlock(); // Release your chopsticks
}
}
}
}
Random random = new Random();
private void eat() {
log.debug("eating...");
Sleeper.sleep(0.5);
}
}
class Chopstick extends ReentrantLock {
String name;
public Chopstick(String name) {
this.name = name;
}
@Override
public String toString() {
return " chopsticks {" + name + '}';
}
}
result
.
.
.
00:54:18.866 c.Philosopher [ Socrates ] - eating…
00:54:18.866 c.Philosopher [ Aristotle ] - eating…
00:54:19.373 c.Philosopher [ Plato ] - eating…
00:54:19.373 c.Philosopher [ Archimedes ] - eating…
00:54:19.881 c.Philosopher [ Socrates ] - eating…
00:54:19.881 c.Philosopher [ Heraclitus ] - eating…
00:54:20.386 c.Philosopher [ Socrates ] - eating…
00:54:20.386 c.Philosopher [ Aristotle ] - eating…
00:54:20.894 c.Philosopher [ Aristotle ] - eating…
00:54:20.894 c.Philosopher [ Socrates ] - eating…
00:54:21.401 c.Philosopher [ Heraclitus ] - eating…
00:54:21.401 c.Philosopher [ Plato ] - eating…
00:54:21.908 c.Philosopher [ Socrates ] - eating…
00:54:21.908 c.Philosopher [ Heraclitus ] - eating…
00:54:22.417 c.Philosopher [ Socrates ] - eating…
00:54:22.417 c.Philosopher [ Heraclitus ] - eating…
.
.
.
.
explain
We can see that there is no deadlock And No thread is hungry , The practice here is to make Chopstick Inherit ReentrantLock class , then Chopstick The object is chopsticks Use tryLock Method If there is competition with other philosophers, give up acquiring , This will naturally disappear Deadlock caused by competition
06. Fair lock
Introduce
Multiple threads acquire locks in the order in which they apply for locks
Source code 
It can be seen that ,ReentrantLock The parameter structure passes true Then the created object is a fair lock ( The default is unfair lock ), Fair locks are generally unnecessary Will reduce concurrency , Then we learn AQS Will analyze its source code
07. Condition variables,
Introduce
synchronized There are also conditional variables in , When we talk about principles Monitor Medium WaitSet, When conditions are not met, enter WaitSet Waiting in the .
ReentrantLock The conditional variable ratio of synchronized The strength is It is the result of multiple conditional variables This is like comparison. synchronized Those threads that do not meet the conditions are waiting for messages in a lounge , and ReentrantLock Support multiple lounges There is a lounge with special smoking conditions There is a lounge for waiting for breakfast Wake up according to the rest room
Usage flow
1.await You need to get the lock before
2.await After execution Can release the lock Get into conditionObject wait for
3.await The thread of is awakened ( Or interrupt Or timeout ) To re compete lock lock
4. competition lock After the lock is successful from await And then go ahead with
Example
It's the same one as before wait/notify Example , This use RenntrantLock Realization
@Slf4j(topic = "c.Test24")
public class Test24 {
static final Object room = new Object();
static boolean hasCigarette = false;
static boolean hasTakeout = false;
static ReentrantLock ROOM = new ReentrantLock();
// Waiting for smoke in the lounge
static Condition waitCigaretteSet = ROOM.newCondition();
// Waiting for takeout
static Condition waitTakeoutSet = ROOM.newCondition();
public static void main(String[] args) {
new Thread(() -> {
ROOM.lock();
try {
log.debug(" Do you have any cigarettes ?[{}]", hasCigarette);
while (!hasCigarette) {
log.debug(" No smoke , Take a break !");
try {
waitCigaretteSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug(" You can start working ");
} finally {
ROOM.unlock();
}
}, " Xiaonan ").start();
new Thread(() -> {
ROOM.lock();
try {
log.debug(" Did the takeout arrive ?[{}]", hasTakeout);
while (!hasTakeout) {
log.debug(" No takeout , Take a break !");
try {
waitTakeoutSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug(" You can start working ");
} finally {
ROOM.unlock();
}
}, " Little girl ").start();
sleep(1);
new Thread(() -> {
ROOM.lock();
try {
hasTakeout = true;
waitTakeoutSet.signal();
} finally {
ROOM.unlock();
}
}, " Take away delivery ").start();
sleep(1);
new Thread(() -> {
ROOM.lock();
try {
hasCigarette = true;
waitCigaretteSet.signal();
} finally {
ROOM.unlock();
}
}, " The cigarette man ").start();
}
}
result
01:20:49.292 c.Test24 [ Xiaonan ] - Do you have any cigarettes ?[false]
01:20:49.295 c.Test24 [ Xiaonan ] - No smoke , Take a break !
01:20:49.295 c.Test24 [ Little girl ] - Did the takeout arrive ?[false]
01:20:49.295 c.Test24 [ Little girl ] - No takeout , Take a break !
01:20:50.300 c.Test24 [ Little girl ] - You can start working
01:20:51.309 c.Test24 [ Xiaonan ] - You can start working
explain
We created two lounges , Xiao Nan didn't get the condition of cigarette The entry is waitCigaretteSet lounge , The little girl didn't get the condition of taking out The entry is waitTakeoutSet This lounge , Compared with the previous use synchronized When Xiaonv and Xiaonan entered before they got the conditions WaitSet, There are more subdivisions here . Wake up later Also wake up according to the rest area .
边栏推荐
- Latex (KAtex) CSDN Greek alphabet representation, mathematical symbols, set symbols, special marks
- R语言使用quantile函数计算向量数据或者dataframe指定数据列的分位数(百分位数)
- Publish the local image to Alibaba cloud warehouse
- A preliminary study of the relationship between combinatorial mathematics and DP, and the derivation of resettable combinatorial formulas
- 家用 NAS 服务器(3)| SSD缓存加速机械硬盘
- Idea select code generation method
- 进程调度的基本过程
- 华为云HCS解决方案笔记HUAWEI CLOUD Stack【面试篇】
- redis过期key的删除策略[通俗易懂]
- Why are there Chinese materials and web pages for foreign chips?
猜你喜欢

(CVPR-2022)BiCnet

According to the e-commerce written on the resume, how does redis realize inventory deduction and prevent oversold?

树莓派ssh登录

Powercli management VMware vCenter one click batch deployment OVA

吃透Chisel语言.21.Chisel时序电路(一)——Chisel寄存器(Register)详解

将本地镜像发布到阿里云仓库
![Mysql database [Database Foundation -- introduction]](/img/a9/429beb3a0be7c82084e803e3165d92.png)
Mysql database [Database Foundation -- introduction]

PC性能监测工具,软件测试人员不可或缺的好帮手

为啥一问 JVM 就 懵B ?

Powercli moves virtual machines from host01 host to host02 host
随机推荐
web安全入门-ssh测试与防御
Boundschecker usage "recommended collection"
树莓派ssh登录
MySQL读写分离的三种实现方案
吃透Chisel语言.21.Chisel时序电路(一)——Chisel寄存器(Register)详解
LeetCode - 最接近的三数之和
R language uses the ggarrange function of ggpubr package to combine multiple images, and uses the ggexport function to save the visual images in BMP format (width parameter specifies width, height par
Codeforces Round #809 (Div. 2)【VP记录】
固态硬盘的工作原理揭秘
攻防世界web题-fakebook
三维点云课程(七)——特征点描述
R language uses dwilcox function to generate Wilcoxon rank sum statistical distribution density function data, and uses plot function to visualize Wilcoxon rank sum statistical distribution density fu
PC性能监测工具,软件测试人员不可或缺的好帮手
R language mapping: coordinate axis setting
BoundsChecker用法「建议收藏」
R语言使用quantile函数计算向量数据或者dataframe指定数据列的分位数(百分位数)
R语言data.table包进行数据分组聚合统计变换(Aggregating transforms)、计算dataframe数据的分组最小值(min)
解密:智能化变电站中PTP时钟同步(北斗时钟服务器)
ACM MM 2022 Oral | DIG: 自监督文字识别的新框架,刷新11个公开场景文字数据集的识别性能,平均提升5%...
Ggarrange function of R language ggpubr package combines and annotates multiple images_ Figure add annotation, annotation, annotation information to the combined image, and add annotation information