Java multithreading – deadlocks
-
What is a deadlock?
A deadlock is a situation in which multiple threads are blocked at the same time, and one or all of them are waiting for a resource to be released. The program cannot run because the thread is blocked indefinitely. Figuratively speaking, a treasure needs two keys to open, and two people come at the same time, each of them with a key, but both of them are waiting for the other to hand over the key to open the treasure, neither of them release their own key. The two were in a stand-off until the developers discovered the situation.
The root cause of deadlocks is the inappropriate use of the “synchronized” keyword to manage thread access to a particular object. The role of the “synchronized” keyword is to ensure that only one thread is allowed to execute a particular block of code at a time, so that the thread that is allowed to execute must first have exclusive access to a variable or object Access to. When a thread accesses an object, it locks the object, and this lock causes other threads that want to access the same object to block until the first thread releases its lock on the object.
For those unfamiliar with synchronized, click here
-
For example
Most deadlocks occur when you don’t know. Let’s use an example to see what a deadlock is.
1. The synchronized nesting.
The synchronized keyword guarantees synchronization when multiple threads access synchronized modified methods. If thread A accesses the method and thread B accesses the method at the same time, thread B will block and wait for thread A to complete. This is where the lock held by synchronized is used. Look at the code:
// First we define two final object locks. Final Object lockA = new Object(); final Object lockB = new Object(); // ProductThreadA implements Runnable{@override public voidrun() {// The thread must sleep for a while to simulate processing data, otherwise the deadlock will not be obvious. Synchronized (lockA){// synchronized (lockA){synchronized (lockA){// synchronized (lockA){// synchronized (lockA){// synchronized (lockA){// synchronized (lockA){// synchronized (lockA)logLog Log. E ("CHAO"."ThreadA lock lockA"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); Synchronized (lockB){// synchronized (lockB)logLog Log. E ("CHAO"."ThreadA lock lockB"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }}}}} // producer B class ProductThreadB implements Runnable{// Producer B class ProductThreadB implements Runnable{// public voidrun() {synchronized (lockB){// synchronizedlogLog Log. E ("CHAO"."ThreadB lock lockB"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lockA){// synchronizedlogLog Log. E ("CHAO"."ThreadB lock lockA"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }}}}} // run ProductThreadA ProductThreadA = new ProductThreadA(); ProductThreadB productThreadB = new ProductThreadB(); Thread threadA = new Thread(productThreadA); Thread threadB = new Thread(productThreadB); threadA.start(); threadB.start();Copy the code
When threadA starts running, it holds the localA object lock and sleeps for 2 seconds, at which point threadB also executes the run object lock. When threadA runs to the second synchronization method and finds that the localB lock is not available (threadB has not released the localB lock),threadA stops there and waits for the localB lock. The localA lock has not yet been released, and threadB waits for the localA lock to be released. So neither thread can continue to execute, enter the deadlock state. Take a look at the results:
10-20 14:54:39. 940, 18162-18178 /? E/CHAO: ThreadA lockA 10-20 14:54:39.940 18162-18179/? E/CHAO: ThreadB lock lockBCopy the code
Four logs should be printed when there is no deadlock, which is an obvious deadlock phenomenon.
-
The cause of deadlocks
When we understand when a deadlock can occur and what a deadlock is, we should try to avoid this error when writing code. The following four conditions must be met for a deadlock to occur. If any of these conditions is not true, the deadlock will not occur.
• Mutually exclusive conditions: Threads require exclusive control over allocated resources, i.e. a resource is owned by only one process for a period of time. If another process requests the resource. The requesting process can only wait.
• No dispossession condition: a resource acquired by a process cannot be seized by another process before it is fully used, that is, it can only be released by the thread that acquired the resource itself (only voluntarily).
• Request and hold conditions: a thread that has held at least one resource, but makes a request for a new resource that has been occupied by another thread, is blocked but holds on to the resource it has acquired.
• Circular waiting condition: There is a circular waiting chain of thread resources in which each thread has acquired a resource that is also requested by the next thread in the chain.
-
The solution to deadlocks is to be honest, avoid deadlocks when writing your own code. I quote other people’s solutions here, but I don’t know much about these solutions, they are too vague without concrete examples.
Source address github.com/WangcWj/Thr…
Welcome to ridicule, give a thumbs-up ~