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。所以我们应该面临僵局,但我们不会。
为什么?
答案 0 :(得分:2)
只有在存在多个锁时才会发生死锁。
在这种情况下,func2
和func1
会在同一lock
监视器(TestClass
的实例)上同步。一旦线程获得此锁定,其他线程将被阻塞,直到它释放锁定。
假设main thread
已输入func1
,这意味着它已获得锁定,其他线程无法同时调用func2
。因为fun1
和fun2
正在使用相同的锁定!在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()
等待锁定同一个对象。