[Java multithreading] deadlock problem

deadlock

Understanding of deadlock : Different threads occupy the synchronization resources needed by the other party without giving up, and are waiting for the other party to give up the synchronization resources they need, thus forming a thread deadlock.

Description :

1. After a deadlock occurs, there will be no exception or prompt, but all threads are blocked and cannot continue.

2. When we use synchronization, we must avoid deadlock

Solution

specialized algorithms and principles

Minimize the definition of synchronization resources

Try to avoid nested synchronization

=========================================================================

First of all, let's look at two pictures to understand the thread states defined by the Thread.State class in JDK:

To implement multithreading, a new thread object must be created in the main thread. The Java language uses objects of the Thread class and its subclasses to represent threads, and usually goes through the following five states during its complete life cycle:

New : When an object of the Thread class or its subclasses is declared and created, the new thread object is in the new state

Ready: After the thread in the newly created state is started(), it will enter the thread queue and wait for the CPU time slice. At this time, it has the conditions to run, but it has not been allocated CPU resources.

Running: When a ready thread is scheduled and obtains CPU resources, it enters the running state. The run() method defines the operation and function of the thread

Blocking: Under certain special circumstances, when it is artificially suspended or performs input and output operations, it will give up the CPU and temporarily suspend its own execution, entering the blocked state

Death: The thread has completed all its work or the thread is forcibly terminated early or an exception causes the end

1: The life cycle of the thread

2: Thread conversion:

=========================================================================

The following is a demonstration of the deadlock problem

code show as below:

public class ThreadTest {
    public static void main(String[] args) {

        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();

        new Thread(){
            @Override
            public void run() {

                synchronized (s1){
                    s1.append("a");
                    s2.append("1");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s2){
                    s1.append("c");
                    s2.append("3");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }){}.start();
    }
}

The running result is shown in the figure:

We can see that the program neither reports an exception nor terminates.

You can look at the following example to understand 

class A {
	public synchronized void foo(B b) {
		System.out.println("当前线程名: " + Thread.currentThread().getName()
				+ " 进入了A实例的foo方法"); // ①
		try {
			Thread.sleep(200);
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		}
		System.out.println("当前线程名: " + Thread.currentThread().getName()
				+ " 企图调用B实例的last方法"); // ③
		b.last();
	}

	public synchronized void last() {
		System.out.println("进入了A类的last方法内部");
	}
}

class B {
	public synchronized void bar(A a) {
		System.out.println("当前线程名: " + Thread.currentThread().getName()
				+ " 进入了B实例的bar方法"); // ②
		try {
			Thread.sleep(200);
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		}
		System.out.println("当前线程名: " + Thread.currentThread().getName()
				+ " 企图调用A实例的last方法"); // ④
		a.last();
	}

	public synchronized void last() {
		System.out.println("进入了B类的last方法内部");
	}
}

public class DeadLock implements Runnable {
	A a = new A();
	B b = new B();

	public void init() {
		Thread.currentThread().setName("主线程");
		// 调用a对象的foo方法
		a.foo(b);
		System.out.println("进入了主线程之后");
	}

	public void run() {
		Thread.currentThread().setName("副线程");
		// 调用b对象的bar方法
		b.bar(a);
		System.out.println("进入了副线程之后");
	}

	public static void main(String[] args) {
		DeadLock dl = new DeadLock();
		new Thread(dl).start();
		dl.init();
	}
}

thanks for watching! ! !

Guess you like

Origin blog.csdn.net/qq_64976935/article/details/128893269