Deadlock issues in Java Multi-threading

Source: Internet
Author: User

Java program basically involves multi-threading, but in multi-threaded environment inevitably encounter thread deadlock problem. Java is not like a database to detect deadlocks, and then processing, the deadlock problem in Java, only through the programmer to write their own code to avoid the possibility of introducing deadlocks to solve.

1. Causes of deadlocks in Java

The simplest case of deadlock in Java is that one thread T1 holds the lock L1 and applies for the lock L2, while the other thread T2 holds the lock L2 and applies for the lock L1 because the default lock request operation is blocked, so thread T1 and T2 are always blocked. led to a deadlock. This is the most easily understood and simplest form of deadlock. But the deadlock in the real world is often more complex than this. There may be multiple threads that form a deadlock loop, such as: Thread T1 holds the lock L1 and applies for the lock L2, while the thread T2 holds the lock L2 and applies for the lock L3, while the thread T3 holds the lock L3 and applies for the lock L1, which leads to a lock-dependent loop: T1-dependent T2 lock L2, T2 relies on T3 lock L3, and T3 relies on T1 lock L1. Thereby led to the deadlock.

From these two examples, we can conclude that the most fundamental cause of the deadlock probability is that the thread obtains a lock L1 in the case of another lock L2, that is, the lock L1 want to contain the lock L2, that is, in the case of obtaining the lock L1, and no release lock L1, To apply for a lock L2, this is the most fundamental cause of the deadlock. Another reason is that the default lock request operation is blocked .

2. How to avoid deadlocks in Java

Now that we know the reason for the possibility of a deadlock, we can circumvent it when coding. Java is an object-oriented programming language, the smallest unit of the program is an object, the object encapsulates the data and operations, so the lock in Java is also in the object unit, the object's built-in lock protects the data in the object's concurrent access. So if we can avoid invoking the synchronization method of other objects in the object's synchronous method, we can avoid the possibility of deadlock. As shown in the code below, there is the possibility of a deadlock:

public class ClassB {    private String address;    // ...        Public synchronized void Method1 () {        //do something    }
// ... ...}
public class ClassA {    private int id;    private String name;    Private ClassB B;    // ...        Public synchronized void M1 () {        //do something        b.method1 ();    }
// ... ...}

The Classa.m1 () method above, in the object's synchronization method, also calls the ClassB synchronization method Method1 (), so there is a possibility of deadlock. We can modify the following to avoid deadlocks:

public class ClassA {    private int id;    private String name;    Private ClassB B;    // ...        public void m2 () {        synchronized (this) {            //do something        }        b.method1 ();    }    // ... ...}

This reduces the scope of the lock, the application of two locks does not intersect, avoids the possibility of deadlock, this is the most rational situation, because the lock does not intersect . But sometimes we are not allowed to do so. At this point, if there is only one M1 in ClassA, you need to obtain a lock on two objects at the same time, and you will not overflow the Instance property B (return B;), but instead enclose the instance property B in the object, and there will be no deadlock. Because the closed loop of the deadlock cannot be formed. However, if there are multiple methods in ClassA that need to acquire locks on two objects at the same time, these methods must acquire locks in the same order.

For example, in the case of bank transfer, we must obtain a lock on two accounts at the same time, in order to operate, two lock requests must cross. At this point we can also break the deadlock of the closed loop, in the case involving the application of two locks at the same time, always in the same order to apply for the lock, such as always first to apply for the ID of the account of the lock, and then apply for the account of the small ID lock, so that can not form the closed loop causing the deadlock.

public class Account {    private int id;    Primary key    private String name;    private double balance;        public void transfer (account from, account to, double money) {        if (From.getid () > To.getid ()) {            synchronized ( From) {                synchronized (to) {                    //Transfer                }            }        }else{            synchronized (to) {                synchronized ( From) {                    //Transfer}}}} public    int getId () {        return ID;}    }

In this case, even if two accounts such as Id=1 and Id=100 's two accounts are transferred to each other, because no matter which line enters upgradeable obtains the lock on the id=100, the other thread will not get the lock on the id=1 (because he did not get the lock on the id=100), Only which line enters upgradeable obtains the lock on the id=100, which thread transfers the first. In addition to using the ID, if there are no such attributes like ID can be compared, you can also use the value of the object's Hashcode () to compare.

As we said above, another reason for deadlocks is that the default lock request operation is blocked, so if we don't use the default blocking lock, we can avoid deadlocks. We can use the Reentrantlock.trylock () method, in a loop, if Trylock () fails to return, then release and acquire the lock and sleep for a short period of time. This breaks the closed loop of the deadlock.

For example: Thread T1 holds the lock L1 and applies for the lock L2, while the thread T2 holds the lock L2 and applies for the lock L3, while the thread T3 holds the lock L3 and applies for the lock L1

At this time if the T3 application lock L1 failed, then T3 release lock L3, and sleep, then T2 can get L3, and then T2 to release L2, L3, so T1 can also get L2 after execution then release the lock L1, L2, and then T3 sleep wake up, also can get L1, L3. Broke the closed loop of the deadlock.

These situations are better handled because they are relevant and it is easy to realize that there is a possibility of deadlocks, which can be guarded. There are many scenarios where it is not obvious that there is a possibility of a deadlock occurring. So we still have to pay attention to:

once we have called the methods of other objects in a synchronous method, or in the scope of the protection of a lock, we need to be careful about ten points :

1) If this method of other objects consumes a long time, then it will result in the lock being held for a long time;

2) If this method of other objects is a synchronous method, then we should pay attention to avoid the possibility of deadlock;

It is best to avoid delaying and synchronizing methods that call other objects in a synchronous method . If not avoided, it is necessary to take the above mentioned coding skills, breaking the deadlock of the closed loop, to prevent the occurrence of deadlocks. At the same time we can use "immutable object" to avoid the use of locks, in some cases can also avoid the sharing of objects, such as a new object to replace the shared object, because the lock is usually on the object, the object is not the same, you can avoid deadlocks, and try to avoid the use of static synchronization method, Because static synchronization is equivalent to a global lock. There are also blocking techniques that can be used: such as stack closures, thread closures, and ThreadLocal, which can reduce the sharing of objects and reduce the likelihood of deadlocks.

Deadlock issues in Java Multi-threading

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.