There is the following code, simulating the transfer between two accounts Situation
void transfer(Account from,Account to,int money){ from.setAmount(from.getAmount()-money); to.setAmount(to.getAmount()+money); }
Under single thread, this code is definitely no problem, but there is a problem under multi-threading
Now lock it, the code after locking is as follows
void transfer(Account from,Account to,int money){ synchronized(from){ synchronized(to){ from.setAmount(from.getAmount()-money); to.setAmount(to.getAmount()+money); } } }
synchronized, that is, object lock, the first synchronized locks the from object, and the second synchronized locks the to object.
In the case of multi-threading, only one thread among multiple threads at the same time can obtain this object lock and operate the code segment in the object lock
But after adding the object lock , there may be a deadlock!
transfer(a,b,100) and transfer(b,a,100) are performed at the same time, that is, while a is transferring money to b, b is also transferring money to a
[1]a Transfer money to b, thread , in order to carry out the transfer operation
Operation [2] The object lock a is urgently needed before the transfer operation can be carried out
Both threads are waiting for other threads in the group to release the lock, and this happens Deadlock!
2. To solve the deadlock
What aspects should we start from?
Generally speaking, for the safety of the program, we must lock the object, so this condition generally cannot be broken
[2 】Break hold and wait, that is, hold and wait
can obtain all resources at one time. In the sample code, the two resources from and to are not obtained at one time, but are obtained in a distributed manner.
Method 1: Add a short timeout to to. Once the attempt to obtain to times out, immediately release the from lock initially held, and try again after a period of time
Get the from and to locks. This is the recommended method
Method 2: Add a global lock to this code to ensure that from and to are obtained at the same time. After the transfer operation is completed, release the global lock. It is relatively safe, but there are many bank accounts and transfer operations are very frequent. Using this method will inevitably cause a serious decrease in performance
[3] Break the loop waiting
Get resources in order , transfer operations are performed according to the size of the Account ID. Accounts with smaller IDs perform transfer operations first, and accounts with larger IDs perform
transfer operations later. But in real life, some things have no ID, that is, no order. At this time, it is necessary to force order to them.
[4] Break the irrevocable waiting
Add timeout, a last resort, the user’s transfer operation failed, and the user’s experience is not good
Personally recommended solution :
Sacrifice the user’s short waiting time and use method 1 in [2]
Related articles:
The concept and solution of deadlock in JavaThe concept of deadlock and the conditions of deadlock
The above is the detailed content of [JAVA] The occurrence and solution of deadlock. For more information, please follow other related articles on the PHP Chinese website!