When a thread holds a lock forever, and the other threads try to acquire the lock, then he is always blocked, and when thread A holds the lock L and wants to acquire the lock m, thread B holds the lock m and simultaneously tries to acquire the lock L, then two threads will wait forever, in the case of simple deadlock, There is a deadlock in which multiple threads wait forever because of a lock dependency on the loop.
1. Lock sequence Deadlock
Here is an illustrated sequence of locks, with the following code:
1 PackageDeadLock;2 3 Public classLeftrightdeadlock {4 Private FinalObject left =NewObject ();5 Private FinalObject right =NewObject ();6 7 Public voidLeftRight ()throwsexception{8 synchronized(left) {9Thread.Sleep (2000);Ten synchronized(right) { OneSystem.out.println ("left-to-right"); A } - } - } the - - Public voidRightleft ()throwsexception{ - synchronized(right) { +Thread.Sleep (2000); - synchronized(left) { +System.out.println ("right-to-left"); A } at } - } - -}View Code
1 PackageDeadLock;2 3 Public classLeftrightthreadextendsThread {4 5 PrivateLeftrightdeadlock D;6 PublicLeftrightthread (Leftrightdeadlock d) {7 This, db=D;8 }9 @OverrideTen Public voidrun () { One Try{ A d.leftright (); -}Catch(Exception ex) { - ex.printstacktrace (); the } - } - -}View Code
1 PackageDeadLock;2 3 Public classRightleftthreadextendsThread {4 5 PrivateLeftrightdeadlock D;6 PublicRightleftthread (Leftrightdeadlock d) {7 This, db=D;8 }9 @OverrideTen Public voidrun () { One Try{ A d.rightleft (); -}Catch(Exception ex) { - ex.printstacktrace (); the } - } - -}View Code
1 PackageDeadLock;2 3 Public classMain {4 Public Static voidMain (string[] args) {5Leftrightdeadlock d =NewLeftrightdeadlock ();6Leftrightthread T1 =NewLeftrightthread (d);7Rightleftthread t2 =NewRightleftthread (d);8 T1.start ();9 T2.start ();Ten } One}View Code
The thread T1 holds the left lock and attempts to obtain the lock of right, while the thread T2 holds the lock of right and tries to obtain a left lock, resulting in a deadlock. The reason for the deadlock is that two threads try to obtain the same lock in different order, and if the lock is requested in the same order, there is no cyclic lock-in dependency, so there is no deadlock.
If all threads acquire locks in a fixed order, then there is no lock sequence deadlock in the program.
2. Dynamic Lock sequence deadlock
Sometimes it is not clear whether there is enough control in the lock order to avoid the deadlock, see the following code for the transfer.
1 Public classtransferaccounts {2 Public voidTransferMoney (account Fromaccount, account Toaccount,DoubleAmountthrowsexception{3 synchronized(fromaccount) {4 synchronized(toaccount) {5 if(Fromaccount.getbalance ()-Amount < 0){6 Throw NewException ();7 }8 Else{9 fromaccount.setbalance (amount);Ten Toaccount.add (amount); One } A } - } - } the}View Code
1 Public classAccount {2 3 //Amount4 Private Doublebalance;5 6 Public DoubleGetBalance () {7 returnbalance;8 }9 Ten Public voidSetbalance (Doublebalance) { One This. Balance =balance; A } - Public voidAddDoubleamount) { -Balance + =amount; the } - Public voidSubtra (Doubleamount) { -Balance-=amount; - } + -}View Code
The above code is a simple implementation of the transfer of funds from one account to another, to obtain the locks of the two account objects before starting the transfer to ensure that the balance of the two accounts is updated atomically. All threads seem to acquire locks in sequential locks, but in fact the order of the locks depends on the order of the TransferMoney parameters to the function, which in turn depends on the external input, and if two threads call TransferMoney at the same time, one of the threads transfers from X to Y, Another thread transfers from Y to X, and a deadlock may occur:
Thread A:transfermoney (Xaccount, Yaccount);
Thread B:transfermoney (Yaccount, Xaccount);
To prevent this from happening, locks must be acquired in order. The following code:
1 Public classtransferaccounts {2 Private Static FinalObject Tielock =NewObject ();3 4 Public voidTransfer (account Fromaccount, account Toaccount,5 DoubleAmountthrowsException {6 if(Fromaccount.getbalance ()-Amount < 0) {7 Throw NewException ();8}Else {9 fromaccount.setbalance (amount);Ten Toaccount.add (amount); One } A } - Public voidTransferMoney (account Fromaccount, account Toaccount, - DoubleAmountthrowsexception{ the intFromhash =Fromaccount.hashcode (); - intTohash =Toaccount.hashcode (); - if(Fromhash <Tohash) { - synchronized(fromaccount) { + synchronized(toaccount) { - Transfer (Fromaccount, Toaccount, amount); + } A } at}Else if(Fromhash >Tohash) { - synchronized(toaccount) { - synchronized(fromaccount) { - Transfer (Fromaccount, Toaccount, amount); - } - } in}Else { - synchronized(tielock) { to synchronized(fromaccount) { + synchronized(toaccount) { - Transfer (Fromaccount, Toaccount, amount); the } * } $ }Panax Notoginseng } - } the +}View Code
In rare cases, two objects may have a relative hashcode value, and this additional lock must be obtained before the lock on the two account can be obtained by adding an additional lock. Thus eliminating the occurrence of deadlocks.
3. Avoidance and diagnosis of deadlock
(1) If a program can only acquire one lock at a time, the lock sequence deadlock is not generated.
(2) If multiple locks must be obtained, the order of locks must be considered in the design, and lock sequence deadlocks will not occur if locks are acquired in a fixed order.
(3) Support timing lock, such as display using the Lock class timer Trylock function in place of the built-in lock, display lock can specify a time-out period, after waiting for more than a certain time Trylock will return a failed message.
Java Multithreading--deadlock