为什么在这种情况下不会出现死锁

时间:2018-05-16 13:43:10

标签: java multithreading thread-safety deadlock synchronized

public class TestClass {

public synchronized void func1() throws InterruptedException {
        System.out.println("func1");
        long a = System.nanoTime();
        func2();

}

public synchronized void func2() throws InterruptedException {
        System.out.println("func2");
        long a = System.nanoTime();
        while (System.nanoTime() - a < 10000000) {
            ;
        }

        func1();

} }

public class ThreadSample extends Thread {

TestClass testClass;
public ThreadSample(TestClass testClass)
{
    this.testClass = testClass;
}
@Override
public void run() {
    try {
        testClass.func2();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}}

public class Main {
public static void main(String[] args) throws InterruptedException {

    TestClass testClass = new TestClass();
    ThreadSample threadSample  = new ThreadSample(testClass);
    threadSample.start();
    testClass.func1();
}}

请看上面的代码。为什么不在这里发生僵局?因为主线程在func1中并想要转到func2但它不能,因为func2被ThreadSample锁定。和ThreadSample也不能去func1。所以我们应该面临僵局,但我们不会。

为什么?

2 个答案:

答案 0 :(得分:2)

只有在存在多个锁时才会发生死锁。

在这种情况下,func2func1会在同一lock监视器(TestClass的实例)上同步。一旦线程获得此锁定,其他线程将被阻塞,直到它释放锁定。

假设main thread已输入func1,这意味着它已获得锁定,其他线程无法同时调用func2。因为fun1fun2正在使用相同的锁定!在fun1中,此线程可以调用fun2,因为synchronized块是可重入的。

答案 1 :(得分:0)

您可以使用func2()替换sleep方法,如下所示,以锁定testClass对象:

public synchronized void func2() throws InterruptedException {
    System.out.println("func2");
    long a = System.nanoTime();
    Thread.sleep(1000000000000L);
    //func1();
}

现在,threadSample线程首先获取锁定(启动后)在func2内等待(保持testClass对象上的锁定)因此main线程可以&#39 ; t甚至进入func1()等待锁定同一个对象。