This article describes the Java deadlock mechanism and inter-thread communication
Dead lock
Deadlock: A phenomenon that occurs when two or more two threads are competing for resources.
Nested cases for synchronizing code blocks
Public classMyLock {//to create two lock objects Public Static FinalObject Obja =NewObject (); Public Static FinalObject OBJB =NewObject ();} Public classDielockextendsThread {Private BooleanFlag; PublicDielock (Booleanflag) { This. Flag =Flag; } @Override Public voidrun () {if(flag) {synchronized(Mylock.obja) {System.out.println ("If Obja"); synchronized(MYLOCK.OBJB) {System.out.println ("If OBJB"); } } } Else { synchronized(MYLOCK.OBJB) {System.out.println ("Else OBJB"); synchronized(Mylock.obja) {System.out.println ("Else Obja"); } } } }} Public classDielockdemo { Public Static voidMain (string[] args) {Dielock dl1=NewDielock (true); Dielock DL2=NewDielock (false); Dl1.start (); Dl2.start (); }}
Avoid deadlocks
There are a number of guidelines that we can use to avoid deadlock situations:
- Avoid nesting blocking: This is the main reason for deadlocks, and if you already have a resource you should avoid blocking another resource. If you run with only one object blocked, it is almost impossible to have a deadlock situation. For example, here is another run () method that does not have a nested block in operation, and the program runs without deadlock and runs successfully.
- block only requests: you should just want the resources you want to run to get blocked, such as the full object resources I'm blocking in the above program. But if we are only interested in one of the fields in which it belongs, then we should block that particular field rather than the complete object.
- avoid waiting indefinitely: If two threads are waiting for the end of the object, an indefinite use of the thread joins, if your thread must wait for the end of another thread, if waiting for the end of the process to join is best prepared for the longest time.
Inter-thread communication
1, Condition newcondition()
Returns a new instance bound to this Lock instance Condition . The lock must be persisted by the current thread before waiting for the condition. The call Condition.await() will atomically release the lock before waiting, and regain the lock before waiting for it to return.
Implementation considerations
ConditionThe actual operation of the instance depends on the Lock implementation, and the implementation must record it.
return: Lock A new instance for this instance Condition
2, public interface Condition
ConditionThe Object monitor methods ( wait , notify and notifyAll ) are decomposed into distinct objects to Lock provide multiple wait sets (Wait-set) for each object by combining these objects with any implementation. This replaces the use of Lock synchronized methods and statements, Condition replacing the use of the Object monitor method.
A condition (also known as a conditional queue or condition variable ) provides a means for a thread to suspend the thread (that is, let it "wait") until another thread that a state condition might now be true notifies it. Because access to this shared state information occurs in different threads, it must be protected so that a form of lock is associated with that condition. The primary property for waiting to provide a condition is to atomically release the associated lock and suspend the current thread as if it were Object.wait done.
ConditionAn instance is essentially bound to a lock. To obtain an instance for a specific Lock instance Condition , use its newCondition() method.
| Method Summary |
void |
await() Causes the current thread to wait until it receives a signal or is interrupted. |
boolean |
await(long time, TimeUnit unit) Causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified wait time. |
long |
awaitNanos(long nanosTimeout) Causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified wait time. |
void |
awaitUninterruptibly() Causes the current thread to remain in a wait state until it receives a signal. |
boolean |
awaitUntil(Date deadline) Causes the current thread to wait until it receives a signal, is interrupted, or reaches a specified deadline. |
void |
signal() Wakes up a waiting thread. |
void |
signalAll() Wakes all waiting threads. |
Example: Suppose you create and start two tasks, one to deposit funds to an account, and another to withdraw money from the same account. When the withdrawal amount is greater than the account balance, the withdrawal thread must wait. Whenever a new deposit is made to the account, the deposit thread must notify the withdrawal thread to try again. If the balance is still up to the withdrawal amount, the withdrawal thread must continue to wait for a new deposit.
In order to synchronize these operations, use a conditional lock newdeposit (that is, add new deposits to the account). If the balance is less than the withdrawal amount, the withdrawal task waits for the newdeposit condition. When the deposit task adds money to the account, the deposit task wakes up waiting for the withdrawal task to be attempted at a time.
The code is as follows:
ImportJava.util.concurrent.ExecutorService;Importjava.util.concurrent.Executors;Importjava.util.concurrent.locks.Condition;ImportJava.util.concurrent.locks.Lock;ImportJava.util.concurrent.locks.ReentrantLock; Public classthreadcooperation {Private StaticAccount Account =NewAccount (); Public Static voidMain (string[] args) {System.out.println ("Thread 1\t\tthread 2\t\tbalance"); //Create a thread pool that contains two threadsExecutorservice executor = Executors.newfixedthreadpool (2); Executor.execute (NewDeposittask ()); Executor.execute (NewWithdrawtask ()); Executor.shutdown (); } //the task of saving money to your account Public Static classDeposittaskImplementsRunnable {@Override Public voidrun () {Try { while(true) {account.deposit (int) (Math.random () * 10) + 1); Thread.Sleep (1000); } } Catch(interruptedexception e) {//TODO auto-generated Catch blockE.printstacktrace (); } } } //the task of withdrawing money from an account Public Static classWithdrawtaskImplementsRunnable {@Override Public voidrun () { while(true) {Account.withdraw (int) (Math.random () * 10) + 1); } } } Public Static classAccount {//Create a lock Private StaticLock lock =NewReentrantlock (); //Create a condition Private StaticCondition newdeposit =lock.newcondition (); Private intBalance = 0; Public intGetBalance () {returnbalance; } Public voidWithdraw (intamount) {Lock.lock (); Try { while(Balance <amount) {System.out.println ("\t\t\twait for a deposit"); Newdeposit.await (); } Balance-=amount; System.out.println ("\t\t\twithdraw" + Amount + "\t\t" +getbalance ()); } Catch(Exception e) {e.printstacktrace (); } finally{lock.unlock ();//Release Lock } } Public voidDepositintamount) {Lock.lock (); Try{Balance+=amount; System.out.println ("Deposit" + Amount + "\t\t\t\t\t" +getbalance ()); Newdeposit.signalall (); } Catch(Exception e) {e.printstacktrace (); } finally{lock.unlock ();//Release Lock } } }}
Java Multithreaded Series 5-deadlock and inter-thread communication