当前位置:网站首页>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
边栏推荐
- Problem a: face recognition
- List interface of collection
- Explication détaillée des fonctions send () et recv () du programme Socket
- Chapter 9 of C language programming (fifth edition of Tan Haoqiang) analysis and answer of exercises for users to establish their own data types
- Alphafpld upgrade alphafold multimer
- Identifier and type conversion
- Problem C: Hanoi Tower III
- JS - accuracy issues
- Learn about I / O flow and file operations
- IDEA查看历史记录【文件历史和项目历史】
猜你喜欢
C set
2022 团体程序设计天梯赛 模拟赛 L2-4 哲哲打游戏 (25 分)
移植tslib时ts_setup: No such file or directory、ts_open: No such file or director
L3-011 direct attack Huanglong (30 points)
QT learning summary
The principle and solution of not allowing pasting in an English Network
12. < tag linked list and common test site synthesis > - lt.234 palindrome linked list
PyMOL usage
Test questions and some space wars
C interface
随机推荐
Idempotency practice operation, explaining idempotency based on business
oracle 查询外键含有逗号分隔的数据
Application and definition of interface
The principle and solution of not allowing pasting in an English Network
【微服务】(十)—— 统一网关Gateway
Cefsharp stores cookies and reads cookies
Supersocket is Used in net5 - command
PyMOL usage
Advanced sorting - fast sorting
IDEA查看历史记录【文件历史和项目历史】
Database SQL -- simulate inserting a large amount of data, importing / exporting database scripts, timestamp conversion and database basics
Explanation keyword of MySQL
Un aperçu des flux d'E / s et des opérations de fichiers de classe de fichiers
第四次作业
L3-011 direct attack Huanglong (30 points)
Log4net is in Net core usage
Common exceptions
2021-08-31
Why is bi so important to enterprises?
数据库表中不建索引,在插入数据时,通过sql语句防止重复添加(转载)