当前位置:网站首页>On the principle of concurrent programming and the art of notify / Park
On the principle of concurrent programming and the art of notify / Park
2022-04-23 03:30:00 【The view of extraordinary is often far away】
1. wait notify
1.1 In principle wait / notify

- Owner Thread discovery condition not met , call wait Method , You can enter WaitSet Turn into WAITING state
- BLOCKED and WAITING All threads are blocked , Not occupy CPU Time slice
- BLOCKED Thread will be Owner Wake up when thread releases lock
- WAITING Thread will be Owner Threads call notify or notifyAll Wake up when , But waking up doesn't mean the person gets the lock immediately , Still need to enter EntryList Re compete , Only after competition to lock , Only then will it have the opportunity to continue the following procedures
1.2API Introduce
- obj.wait() Let in object Monitor thread to waitSet wait for ( Can release the lock )
- obj.notify() stay object It's going on waitSet Pick one of the waiting threads to wake up ( Notification does not release the lock , until notify End of execution )
- obj.notifyAll() Give Way object It's going on waitSet All the waiting threads wake up
They are all means of collaboration between threads , All belong to Object Object method . You must get the lock for this object , To call these methods ( be in owner Call in state wait/notify), Otherwise it will be reported IllegalMonitorStateException It's abnormal
final static Object obj = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (obj) {
log.debug(" perform ....");
try {
obj.wait(); // Let the thread in obj Keep waiting on
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug(" Other code ....");
}
}).start();
new Thread(() -> {
synchronized (obj) {
log.debug(" perform ....");
try {
obj.wait(); // Let the thread in obj Keep waiting on
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug(" Other code ....");
}
}).start();
// The main thread executes in two seconds
sleep( 2 );
log.debug(" Wake up the obj On other threads ");
synchronized (obj) {
obj.notify(); // Wake up the obj Last thread
// obj.notifyAll(); // Wake up the obj All waiting threads on
}
}
notify A result of
20:00:53.096 [Thread-0] c.TestWaitNotify - perform ....
20:00:53.099 [Thread-1] c.TestWaitNotify - perform ....
20:00:55.096 [main] c.TestWaitNotify - Wake up the obj On other threads
20:00:55.096 [Thread-0] c.TestWaitNotify - Other code ....
notifyAll Result
19:58:15.457 [Thread-0] c.TestWaitNotify - perform ....
19:58:15.460 [Thread-1] c.TestWaitNotify - perform ....
19:58:17.456 [main] c.TestWaitNotify - Wake up the obj On other threads
19:58:17.456 [Thread-1] c.TestWaitNotify - Other code ....
19:58:17.456 [Thread-0] c.TestWaitNotify - Other code ....
- wait() Method releases the lock on the object ( The bottom tone is wait(0)), Get into WaitSet Waiting area , This allows other threads to get the lock of the object ( Give up cpu Executive power ) Wait indefinitely , until notify until
- wait(long n) A time-bound wait , To n End waiting in milliseconds , Or by notify
- One more wait(time1,time2) Methods ,time2 The unit of measurement is nanoseconds , But in fact, no matter what its value is , All are time1+1
2. wait notify The right posture
2.1sleep( n) and wait n) The difference between
- sleep yes Thread Method , and wait yes Object Methods
- sleep There's no need to force and synchronized In combination with , but wait Need and synchronized Together with ( Otherwise, throw it out of order )
- sleep While sleeping , Object locks will not be released , but wait The object lock is released while waiting .( They all gave up cpu The enforcement of )
- Their state TIMED_WAITING
2.2 Case comparison
step 1
Think about the following solutions , Why? ?
static final Object room = new Object();
static boolean hasCigarette = false;
static boolean hasTakeout = false;
new Thread(() -> {
synchronized (room) {
log.debug(" Do you have any cigarettes ?[{}]", hasCigarette);
if (!hasCigarette) {
log.debug(" No smoke , Take a break !");
sleep( 2 );
}
log.debug(" Do you have any cigarettes ?[{}]", hasCigarette);
if (hasCigarette) {
log.debug(" You can start working ");
}
}
}, " Xiaonan ").start();
for (int i = 0 ; i < 5 ; i++) {
new Thread(() -> {
synchronized (room) {
log.debug(" You can start working ");
}
}, " Other people ").start();
}
sleep( 1 );
new Thread(() -> {
// Can you add synchronized (room)?
hasCigarette = true;
log.debug(" Here comes the smoke !");
}, " The cigarette man ").start();
Output
20:49:49.883 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[false]
20:49:49.887 [ Xiaonan ] c.TestCorrectPosture - No smoke , Take a break !
20:49:50.882 [ The cigarette man ] c.TestCorrectPosture - Here comes the smoke !
20:49:51.887 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[true]
20:49:51.887 [ Xiaonan ] c.TestCorrectPosture - You can start working
20:49:51.887 [ Other people ] c.TestCorrectPosture - You can start working
20:49:51.887 [ Other people ] c.TestCorrectPosture - You can start working
20:49:51.888 [ Other people ] c.TestCorrectPosture - You can start working
20:49:51.888 [ Other people ] c.TestCorrectPosture - You can start working
20:49:51.888 [ Other people ] c.TestCorrectPosture - You can start working
- Other working threads , All the time , Efficiency is too low
- Xiaonan thread must get enough sleep 2s And then wake up , Even if the cigarettes are delivered in advance , I can't wake up right now
- The code for delivering cigarettes is added synchronized (room) after , It's like Xiao Nan sleeping inside with the door locked , There's no way cigarettes can get through the door ,main No addition synchronized It's like main The thread came in through the window
- resolvent , Use wait - notify Mechanism
step 2
Think about the following implementation , Why? ?
new Thread(() -> {
synchronized (room) {
log.debug(" Do you have any cigarettes ?[{}]", hasCigarette);
if (!hasCigarette) {
log.debug(" No smoke , Take a break !");
try {
room.wait( 2000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug(" Do you have any cigarettes ?[{}]", hasCigarette);
if (hasCigarette) {
log.debug(" You can start working ");
}
}
}, " Xiaonan ").start();
for (int i = 0 ; i < 5 ; i++) {
new Thread(() -> {
synchronized (room) {
log.debug(" You can start working ");
}
}, " Other people ").start();
}
sleep( 1 );
new Thread(() -> {
synchronized (room) {
hasCigarette = true;
log.debug(" Here comes the smoke !");
room.notify();
}
}, " The cigarette man ").start();
Output
20:51:42.489 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[false]
20:51:42.493 [ Xiaonan ] c.TestCorrectPosture - No smoke , Take a break !
20:51:42.493 [ Other people ] c.TestCorrectPosture - You can start working
20:51:42.493 [ Other people ] c.TestCorrectPosture - You can start working
20:51:42.494 [ Other people ] c.TestCorrectPosture - You can start working
20:51:42.494 [ Other people ] c.TestCorrectPosture - You can start working
20:51:42.494 [ Other people ] c.TestCorrectPosture - You can start working
20:51:43.490 [ The cigarette man ] c.TestCorrectPosture - Here comes the smoke !
20:51:43.490 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[true]
20:51:43.490 [ Xiaonan ] c.TestCorrectPosture - You can start working
It solves the problem of thread blocking of other working threads
But what if there are other threads waiting for conditions ?(notify It's random wake-up , False awakening may occur )
step 3
new Thread(() -> {
synchronized (room) {
log.debug(" Do you have any cigarettes ?[{}]", hasCigarette);
if (!hasCigarette) {
log.debug(" No smoke , Take a break !");
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug(" Do you have any cigarettes ?[{}]", hasCigarette);
if (hasCigarette) {
log.debug(" You can start working ");
} else {
log.debug(" Didn't do it ...");
}
}
}, " Xiaonan ").start();
new Thread(() -> {
synchronized (room) {
Thread thread = Thread.currentThread();
log.debug(" Did the takeout arrive ?[{}]", hasTakeout);
if (!hasTakeout) {
log.debug(" No takeout , Take a break !");
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug(" Did the takeout arrive ?[{}]", hasTakeout);
if (hasTakeout) {
log.debug(" You can start working ");
} else {
log.debug(" Didn't do it ...");
}
}
}, " Little girl ").start();
sleep( 1 );
new Thread(() -> {
synchronized (room) {
hasTakeout = true;
log.debug(" Here's the takeout !");
room.notify();
}
}, " Take away delivery ").start();
Output
20:53:12.173 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[false]
20:53:12.176 [ Xiaonan ] c.TestCorrectPosture - No smoke , Take a break !
20:53:12.176 [ Little girl ] c.TestCorrectPosture - Did the takeout arrive ?[false]
20:53:12.176 [ Little girl ] c.TestCorrectPosture - No takeout , Take a break !
20:53:13.174 [ Take away delivery ] c.TestCorrectPosture - Here's the takeout !
20:53:13.174 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[false]
20:53:13.174 [ Xiaonan ] c.TestCorrectPosture - Didn't do it ...
notify Only one can wake up randomly WaitSet Thread in , At this time, if there are other threads waiting , Then the correct thread may not wake up , be called 【 spurious wakeup 】
resolvent , Change it to notifyAll
step 4
new Thread(() -> {
synchronized (room) {
hasTakeout = true;
log.debug(" Here's the takeout !");
room.notifyAll();
}
}, " Take away delivery ").start();
Output
20:55:23.978 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[false]
20:55:23.982 [ Xiaonan ] c.TestCorrectPosture - No smoke , Take a break !
20:55:23.982 [ Little girl ] c.TestCorrectPosture - Did the takeout arrive ?[false]
20:55:23.982 [ Little girl ] c.TestCorrectPosture - No takeout , Take a break !
20:55:24.979 [ Take away delivery ] c.TestCorrectPosture - Here's the takeout !
20:55:24.979 [ Little girl ] c.TestCorrectPosture - Did the takeout arrive ?[true]
20:55:24.980 [ Little girl ] c.TestCorrectPosture - You can start working
20:55:24.980 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[false]
20:55:24.980 [ Xiaonan ] c.TestCorrectPosture - Didn't do it ...
use notifyAll Only solve the wake-up problem of a thread , But use if + wait There is only one chance to judge , Once the conditions are not established , There is no chance to re judge
resolvent , use while + wait, When conditions don't hold , Again wait
step 5
take if Change it to while( Yes, it will wait Put it in while In circulation )
if (!hasCigarette) {
log.debug(" No smoke , Take a break !");
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
After the changes (wait Method is notify The following code will be executed after , So here Will not lead to while Cycle idling )
while (!hasCigarette) {
log.debug(" No smoke , Take a break !");
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Output
20:58:34.322 [ Xiaonan ] c.TestCorrectPosture - Do you have any cigarettes ?[false]
20:58:34.326 [ Xiaonan ] c.TestCorrectPosture - No smoke , Take a break !
20:58:34.326 [ Little girl ] c.TestCorrectPosture - Did the takeout arrive ?[false]
20:58:34.326 [ Little girl ] c.TestCorrectPosture - No takeout , Take a break !
20:58:35.323 [ Take away delivery ] c.TestCorrectPosture - Here's the takeout !
20:58:35.324 [ Little girl ] c.TestCorrectPosture - Did the takeout arrive ?[true]
20:58:35.324 [ Little girl ] c.TestCorrectPosture - You can start working
20:58:35.324 [ Xiaonan ] c.TestCorrectPosture - No smoke , Take a break !
2.3 General writing method
synchronized(lock) {
while( Conditions not established ) {
lock.wait();
}
// work
}
// Another thread
synchronized(lock) {
lock.notifyAll();
}
3. Park & Unpark
3.1 Basic use
They are LockSupport Methods in class
// Pause current thread
LockSupport.park();
// Stop pause
LockSupport.unpark( Pause thread object )
First park Again unpark
Thread t1 = new Thread(() -> {
log.debug("start...");
sleep( 1 );
log.debug("park...");
LockSupport.park();
log.debug("resume...");
},"t1");
t1.start();
sleep( 2 );
log.debug("unpark...");
LockSupport.unpark(t1);
Output
18:42:52.585 c.TestParkUnpark [t1] - start...
18:42:53.589 c.TestParkUnpark [t1] - park...
18:42:54.583 c.TestParkUnpark [main] - unpark...
18:42:54.583 c.TestParkUnpark [t1] - resume...
First unpark Again park
Thread t1 = new Thread(() -> {
log.debug("start...");
sleep( 2 );// Sleeping
log.debug("park...");
LockSupport.park();
log.debug("resume...");
}, "t1");
t1.start();
sleep( 1 );
log.debug("unpark...");
LockSupport.unpark(t1);
Output
18:43:50.765 c.TestParkUnpark [t1] - start...
18:43:51.764 c.TestParkUnpark [main] - unpark...
18:43:52.769 c.TestParkUnpark [t1] - park... // No longer park 了 , But if this is another tune park Will stop
18:43:52.769 c.TestParkUnpark [t1] - resume...
characteristic :
And Object Of wait & notify comparison
- wait,notify and notifyAll Must cooperate Object Monitor Use it together , and park,unpark No need
- park & unpark It's based on threads 【 Blocking 】 and 【 Wake up the 】 Threads , and notify Only one waiting thread can be wakened randomly ,notifyAll Is to wake up all waiting threads , It's not that 【 accurate 】
- park & unpark You can start with unpark, and wait & notify Not first notify
3.2 In principle park & unpark
Each thread has its own Parker object , It's made up of three parts _counter ,_cond and _mutex Make a comparison
Thread is like a traveler ,Parker Like his backpack , Conditional variables are like tents in backpacks ( Blocking queues )._counter It's like spare dry food in a backpack (0 To exhaust ,1 For the sake of sufficiency )
- call park It depends on whether you need to stop and rest
- If the spare dry food runs out , So get into the tent and rest
- If there's enough dry food in reserve , Then there is no need to stay , To move forward
- call unpark, It's like filling dry food
- If the thread is still in the tent , Just wake him up and let him move on
- If the thread is still running , So next time he calls park when , Just consume spare dry food , No need to stop and move on
- Because the backpack space is limited , Multiple calls unpark Only one spare dry food will be added
First call park Call again unpark Method :

- Current thread call Unsafe.park() Method
- Check _counter , This situation is 0, At this time , get _mutex The mutex
- Thread entry _cond Conditional variables block
- Set up _counter = 0

- call Unsafe.unpark(Thread_0) Method , Set up _counter by 1
- Wake up the _cond In a conditional variable Thread_0
- Thread_0 Resume operation
- Set up _counter by 0// That's the next tune park Method will block
First call unpark Method , Call again park Method ** ( First unpark2 Time ,park It will be cleared at one time 0, Again park It still blocks )**
First call park The method will not stop , The second readjustment will stop

- call Unsafe.unpark(Thread_0) Method , Set up _counter by 1
- Current thread call Unsafe.park() Method
- Check _counter , This situation is 1, At this time, the thread does not need to block , Continue operation // First call park It won't stop
- Set up _counter by 0// Second call park Will stop
4 Re understand thread state transitions

Let's say we have threads Thread t
4.1 situation 1 NEW --> RUNNABLE
- When calling t.start() When the method is used , from NEW --> RUNNABLE
4.2 situation 2 RUNNABLE <–> WAITING
t Thread use synchronized(obj) After getting the object lock
- call obj.wait() When the method is used ,t The thread from RUNNABLE --> WAITING
- call obj.notify(),obj.notifyAll(),t.interrupt() when // At this time, they all enter block state
- The competition is successful ,t The thread from WAITING --> RUNNABLE
- The competition lock failed ,t The thread from WAITING --> BLOCKED
public class TestWaitNotify {
final static Object obj = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (obj) {
log.debug(" perform ....");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug(" Other code ...."); // The breakpoint
}
},"t1").start();
new Thread(() -> {
synchronized (obj) {
log.debug(" perform ....");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug(" Other code ...."); // The breakpoint
}
},"t2").start();
sleep(0.5);
log.debug(" Wake up the obj On other threads ");
synchronized (obj) {
obj.notifyAll(); // Wake up the obj All waiting threads on The breakpoint
}
}
}
4.3 situation 3 RUNNABLE <–> WAITING
- Current thread call t.join() When the method is used , The current thread starts from RUNNABLE --> WAITING
- Note that the current thread is t Wait on the monitor of the thread object
- t End of thread run , Or called... Of the current thread interrupt() when , The current thread starts from WAITING --> RUNNABLE
4.4 situation 4 RUNNABLE <–> WAITING
- Current thread call LockSupport.park() Method causes the current thread to run from RUNNABLE --> WAITING
- call LockSupport.unpark( Target thread ) Or called a thread Of interrupt(), Will cause the target thread to run from WAITING -->
RUNNABLE
4.5 situation 5 RUNNABLE <–> TIMED_WAITING
t Thread use synchronized(obj) After getting the object lock
- call obj.wait(long n) When the method is used ,t The thread from RUNNABLE --> TIMED_WAITING
- t Thread waiting time exceeded n millisecond , Or call obj.notify(),obj.notifyAll(),t.interrupt() when
- The competition is successful ,t The thread from TIMED_WAITING --> RUNNABLE
- The competition lock failed ,t The thread from TIMED_WAITING --> BLOCKED
4.6 situation 6 RUNNABLE <–> TIMED_WAITING
- Current thread call t.join(long n) When the method is used , The current thread starts from RUNNABLE --> TIMED_WAITING
- Note that the current thread is t Wait on the monitor of the thread object
- The current thread has been waiting longer than n millisecond , or t End of thread run , Or called... Of the current thread interrupt() when , The current thread starts from
TIMED_WAITING --> RUNNABLE
4.7 situation 7 RUNNABLE <–> TIMED_WAITING
- Current thread call Thread.sleep(long n), The current thread starts from RUNNABLE --> TIMED_WAITING
- The current thread has been waiting longer than n millisecond , The current thread starts from TIMED_WAITING --> RUNNABLE
4.8 situation 8 RUNNABLE <–> TIMED_WAITING
- Current thread call LockSupport.parkNanos(long nanos) or LockSupport.parkUntil(long millis) when , When the front line
Cheng Cong RUNNABLE --> TIMED_WAITING - call LockSupport.unpark( Target thread ) Or called a thread Of interrupt(), Or waiting for a timeout , Will cause the target thread to run from
TIMED_WAITING–> RUNNABLE
4.9 situation 9 RUNNABLE <–> BLOCKED
- t Thread use synchronized(obj) If the race fails when an object lock is acquired , from RUNNABLE --> BLOCKED
- a obj The synchronization block of the lock thread is executed , Will wake up all BLOCKED The threads of the , If one t Thread contention succeeded , from BLOCKED --> RUNNABLE, Other failed threads still BLOCKED
4.10 situation 10 RUNNABLE <–> TERMINATED
All the code of the current thread is running , Get into TERMINATED
5. More locks
Lots of irrelevant locks
A big room has two functions : sleep 、 Study , Irrelevant .
Now Xiao Nan has to learn , The little girl wants to sleep , But if you only use one room ( An object lock ) Words , Then the concurrency is very low
The solution is to prepare multiple rooms ( Multiple object locks )
for example
class BigRoom {
public void sleep() {
synchronized (this) {
log.debug("sleeping 2 Hours ");
Sleeper.sleep( 2 );
}
}
public void study() {
synchronized (this) {
log.debug("study 1 Hours ");
Sleeper.sleep( 1 );
}
}
}
================================
BigRoom bigRoom = new BigRoom();
new Thread(() -> {
bigRoom.compute();
}," Xiaonan ").start();
new Thread(() -> {
bigRoom.sleep();
}," Little girl ").start();
perform
A result
12:13:54.471 [ Xiaonan ] c.BigRoom - study 1 Hours
12:13:55.476 [ Little girl ] c.BigRoom - sleeping 2 Hours
improvement
class BigRoom {
private final Object studyRoom = new Object();
private final Object bedRoom = new Object();
public void sleep() {
synchronized (bedRoom) {
log.debug("sleeping 2 Hours ");
Sleeper.sleep( 2 );
}
}
public void study() {
synchronized (studyRoom) {
log.debug("study 1 Hours ");
Sleeper.sleep( 1 );
}
}
}
An execution result
12:15:35.069 [ Xiaonan ] c.BigRoom - study 1 Hours
12:15:35.069 [ Little girl ] c.BigRoom - sleeping 2 Hours
Subdivide the granularity of locks
- benefits , It can enhance concurrency
- Disadvantage , If a thread needs to acquire multiple locks at the same time , It's prone to deadlock
6 Activity
6.1 Deadlock
There are cases like this : A thread needs to acquire multiple locks at the same time , At this time, deadlock is easy to occur
t1 Threads get A object lock , Next, I want to get B The lock of the object t2 Threads get B object lock , Next, I want to get A The lock of the object example :
Object A = new Object();
Object B = new Object();
Thread t1 = new Thread(() -> {
synchronized (A) {
log.debug("lock A");
sleep( 1 );
synchronized (B) {
log.debug("lock B");
log.debug(" operation ...");
}
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (B) {
log.debug("lock B");
sleep(0.5);
synchronized (A) {
log.debug("lock A");
log.debug(" operation ...");
}
}
}, "t2");
t1.start();
t2.start();
result
12:22:06.962 [t2] c.TestDeadLock - lock B
12:22:06.962 [t1] c.TestDeadLock - lock A
6.1.1 Positioning deadlocks
Deadlock detection can use jconsole Tools , Or use jps Positioning process id, Reuse jstack Positioning deadlocks :
cmd > jps
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
12320 Jps
22816 KotlinCompileDaemon
33200 TestDeadLock // JVM process
11508 Main
28468 Launcher
cmd > jstack 33200
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
2018 -12-29 05 :51:40
Full thread dump Java HotSpot(TM) 64 -Bit Server VM (25.91-b14 mixed mode):
"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000003525000 nid=0x2f60 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE
"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001eb69000 nid=0xd40 waiting for monitor entry[0x000000001f54f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)
- waiting to lock <0x000000076b5bf1c0> (a java.lang.Object)
- locked <0x000000076b5bf1d0> (a java.lang.Object)
at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
"Thread-0" #11 prio=5 os_prio=0 tid=0x000000001eb68800 nid=0x1b28 waiting for monitor entry
[0x000000001f44f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)
waiting to lock <0x000000076b5bf1d0> (a java.lang.Object)
locked <0x000000076b5bf1c0> (a java.lang.Object)
at thread.TestDeadLock$$Lambda$1/495053715.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
// Omit some output
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x000000000361d378 (object 0x000000076b5bf1c0, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x000000000361e768 (object 0x000000076b5bf1d0, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)
- waiting to lock <0x000000076b5bf1c0> (a java.lang.Object)
- locked <0x000000076b5bf1d0> (a java.lang.Object)
at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
"Thread-0":
at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)
- waiting to lock <0x000000076b5bf1d0> (a java.lang.Object)
- locked <0x000000076b5bf1c0> (a java.lang.Object)
at thread.TestDeadLock$$Lambda$1/495053715.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Found 1 deadlock.
To avoid deadlock, pay attention to the locking sequence
In addition, if a thread enters an dead loop , Cause other threads to wait , In this case linux You can go through top First of all, I'll go to
CPU Take up high Java process , recycling top -Hp process id To locate which thread , Last but not least jstack screening
6.1.2 The dining problem of philosophers

There are five philosophers , Sitting around the round table .
They only do two things , Think and eat , Think for a while and have a meal , Think after dinner .
Eat with two chopsticks , There are... On the table 5 Chopsticks , Every philosopher has a chopstick on his left and right .
If chopsticks are held by people around you , I have to wait
Chopsticks
class Chopstick {
String name;
public Chopstick(String name) {
this.name = name;
}
@Override
public String toString() {
return " chopsticks {" + name + '}';
}
}
Philosophers
class Philosopher extends Thread {
Chopstick left;
Chopstick right;
public Philosopher(String name, Chopstick left, Chopstick right) {
super(name);
this.left = left;
this.right = right;
}
private void eat() {
log.debug("eating...");
Sleeper.sleep( 1 );
}
@Override
public void run() {
while (true) {
// Get left chopsticks
synchronized (left) {
// Get the right chopsticks
synchronized (right) {
// having dinner
eat();
}
// Put down your right chopsticks
}
// Put down your left chopsticks
}
}
}
dining
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();
Not much execution will , It can't be carried out
12:33:15.575 [ Socrates ] c.Philosopher - eating...
12:33:15.575 [ Aristotle ] c.Philosopher - eating...
12:33:16.580 [ Archimedes ] c.Philosopher - eating...
12:33:17.580 [ Archimedes ] c.Philosopher - eating...
// It's stuck here , Don't run down
Use jconsole Detection of deadlock , Find out
-------------------------------------------------------------------------
name : Archimedes
state : cn.itcast.Chopstick@1540e19d ( chopsticks 1 ) Upper BLOCKED, The owner : Socrates
Total blocked : 2 , Total wait count : 1
stack trace :
cn.itcast.Philosopher.run(TestDinner.java: 48 )
Locked cn.itcast.Chopstick@ 6 d6f6e28 ( chopsticks 5 )
name : Socrates
state : cn.itcast.Chopstick@ 677327 b6 ( chopsticks 2 ) Upper BLOCKED, The owner : Plato
Total blocked : 2 , Total wait count : 1
stack trace :
cn.itcast.Philosopher.run(TestDinner.java: 48 )
Locked cn.itcast.Chopstick@1540e19d ( chopsticks 1 )
name : Plato
state : cn.itcast.Chopstick@ 14 ae5a5 ( chopsticks 3 ) Upper BLOCKED, The owner : Aristotle
Total blocked : 2 , Total wait count : 0
stack trace :
cn.itcast.Philosopher.run(TestDinner.java: 48 )
Locked cn.itcast.Chopstick@ 677327 b6 ( chopsticks 2 )
name : Aristotle
state : cn.itcast.Chopstick@ 7 f31245a ( chopsticks 4 ) Upper BLOCKED, The owner : Heraclitus
Total blocked : 1 , Total wait count : 1
stack trace :
cn.itcast.Philosopher.run(TestDinner.java: 48 )
Locked cn.itcast.Chopstick@ 14 ae5a5 ( chopsticks 3 )
name : Heraclitus
state : cn.itcast.Chopstick@ 6 d6f6e28 ( chopsticks 5 ) Upper BLOCKED, The owner : Archimedes
Total blocked : 2 , Total wait count : 0
stack trace :
cn.itcast.Philosopher.run(TestDinner.java: 48 )
Locked cn.itcast.Chopstick@ 7 f31245a ( chopsticks 4 )
public class TestLiveLock {
static volatile int count = 10 ;
This thread did not end as expected , The situation that cannot be implemented , Classified as 【 Activity 】 problem , In addition to deadlocks , There are also two cases: the living lock and the hungry
6.2 Live lock
Livelocks occur when two threads change each other's end conditions , In the end, no one can end , for example
static final Object lock = new Object();
public static void main(String[] args) {
new Thread(() -> {
// Expectations are reduced to 0 Exit loop
while (count > 0 ) {
sleep(0.2);
count--;
log.debug("count: {}", count);
}
}, "t1").start();
new Thread(() -> {
// Expectation exceeds 20 Exit loop
while (count < 20 ) {
sleep(0.2);
count++;
log.debug("count: {}", count);
}
}, "t2").start();
}
}
The difference from deadlock , The livelock is always running , It just doesn't end properly . The solution is to add random sleep time .
6.3 hunger
Many tutorials define hunger as , Because the priority of a thread is too low , Never get CPU Scheduling execution , It can't end , Hunger is not easy to demonstrate , Talking about read-write locks involves hunger
Let me talk about an example of thread starvation I encountered , Let's first look at the use of sequential locking ( Such as the first A after B) To solve the previous deadlock problem

Sequential locking solution

notes : The content is transferred from their own language , The content is organized from the video course Learn more about concurrent programming .
版权声明
本文为[The view of extraordinary is often far away]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204220616492480.html
边栏推荐
- 2022 团体程序设计天梯赛 模拟赛 L2-4 哲哲打游戏 (25 分)
- Unity Basics
- Codeforces Round #784 (Div. 4)题解 (第一次AK cf (XD
- 浅学一下I/O流和File类文件操作
- 2022 团体程序设计天梯赛 模拟赛 1-8 均是素数 (20 分)
- Identifier and type conversion
- Super easy to use asynchronous export function of Excel
- Visual programming - Experiment 1
- List interface of collection
- Is it difficult to choose binary version control tools? After reading this article, you will find the answer
猜你喜欢

7-1 introduction to finance
![Super easy to use [general excel import function]](/img/9b/ef18d1b92848976b5a141af5f239b5.jpg)
Super easy to use [general excel import function]

【微服务】(十)—— 统一网关Gateway

Codeforces Round #784 (Div. 4)題解 (第一次AK cf (XD

Codeforces round 784 (Div. 4) (AK CF (XD) for the first time)

Test questions and some space wars

MySQL query specifies that a row is sorted to the first row

Development record of primary sensitive word detection

Build websocket server in. Net5 webapi

Unity knowledge points (ugui 2)
随机推荐
关于idea调试模式下启动特别慢的优化
Detailed description of MySQL index [B + tree index, hash index, full-text index, overlay index]
Three types of cyclic structure
socket編程 send()與 recv()函數詳解
Application and definition of interface
ThreadLocal test multithreaded variable instance
you need to be root to perform this command
浅学一下I/O流和File类文件操作
Build websocket server in. Net5 webapi
Variable definition and use
月薪10k-20k都无法回答的事务问题,你会吗?
移植tslib时ts_setup: No such file or directory、ts_open: No such file or director
oracle 查询外键含有逗号分隔的数据
2022 团体程序设计天梯赛 模拟赛 L2-3 浪漫侧影 (25 分)
Why is bi so important to enterprises?
深度学习笔记(二)——激活函数原理与实现
Database - MySQL -- Navicat import SQL error 1067 - invalid default value for 'paydate‘
List interface of collection
Unity knowledge points (ugui)
C-11 problem h: treasure chest 2