почему в этой ситуации не возникает тупиковая ситуация - PullRequest
0 голосов
/ 16 мая 2018
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 голосов
/ 16 мая 2018

Вы можете заменить свой метод 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 не может даже войти в func1(), ожидая блокировки на том же объекте.

0 голосов
/ 16 мая 2018

Мертвая блокировка возникает только при наличии нескольких блокировок.

В этом случае func2 и func1 синхронизируются на одном и том же мониторе lock (экземпляр TestClass).Как только поток получит эту блокировку, другие потоки будут заблокированы, пока она не снимет блокировку.


Предположим, main thread ввел func1, что означает, что он получил блокировку, другие потоки не могут одновременно вызывать func2.Потому что fun1 и fun2 работают с одной и той же блокировкой!И в fun1 этот поток может вызвать fun2, потому что блок synchronized является повторно входящим.

...