там вызвано тупиковое состояние и посоветуйте мне как исправить и мне нужны общие советы - PullRequest
0 голосов
/ 04 апреля 2019

я изучаю многопоточность Java.есть вызванное тупиковое состояние и посоветуйте мне, как исправить, и мне нужны общие советы.Я понял, что означает концепция тупика, но это может решить проблему на одном.вот код:

java Util class:

// in multithreading. 
class Util 
{ 
    // Util class to sleep a thread 
    static void sleep(long millis) 
    { 
        try
        { 
            Thread.sleep(millis); 
        } 
        catch (InterruptedException e) 
        { 
            e.printStackTrace(); 
        } 
    } 
} 

java Общий класс:

// This class is shared by both threads 
class Shared 
{ 
    // first synchronized method 
    synchronized void test1(Shared s2) 
    { 
        System.out.println("test1-begin"); 
        Util.sleep(1000); 

        // taking object lock of s2 enters 
        // into test2 method 
        s2.test2(this); 
        System.out.println("test1-end"); 
    } 

    // second synchronized method 
    synchronized void test2(Shared s1) 
    { 
        System.out.println("test2-begin"); 
        Util.sleep(1000); 

        // taking object lock of s1 enters 
        // into test1 method 
        s1.test1(this); 
        System.out.println("test2-end"); 
    } 
} 

java Thread1 класс:

class Thread1 extends Thread 
{ 
    private Shared s1; 
    private Shared s2; 

    // constructor to initialize fields 
    public Thread1(Shared s1, Shared s2) 
    { 
        this.s1 = s1; 
        this.s2 = s2; 
    } 

    // run method to start a thread 
    @Override
    public void run() 
    { 
        // taking object lock of s1 enters 
        // into test1 method 
        s1.test1(s2); 
    } 
} 

javaКласс Thread2:

class Thread2 extends Thread 
{ 
    private Shared s1; 
    private Shared s2; 

    // constructor to initialize fields 
    public Thread2(Shared s1, Shared s2) 
    { 
        this.s1 = s1; 
        this.s2 = s2; 
    } 

    // run method to start a thread 
    @Override
    public void run() 
    { 
        // taking object lock of s2 
        // enters into test2 method 
        s2.test2(s1); 
    } 
}

И, наконец, класс GFC для основного метода:

public class GFG 
{ 
    public static void main(String[] args) 
    { 
        // creating one object 
        Shared s1 = new Shared(); 

        // creating second object 
        Shared s2 = new Shared(); 

        // creating first thread and starting it 
        Thread1 t1 = new Thread1(s1, s2); 
        t1.start(); 

        // creating second thread and starting it 
        Thread2 t2 = new Thread2(s1, s2); 
        t2.start(); 

        // sleeping main thread 
        Util.sleep(2000); 
    } 
}

1 Ответ

4 голосов
/ 04 апреля 2019

Код, который вы указали, действительно вызывает тупик. Изначально t1 получает внутреннюю блокировку для s1, а t2 получает блокировку для s2. Затем t1 пытается получить блокировку s2, все еще удерживая блокировку s1. Поскольку блокировка s2 удерживается t2, t1 будет блокировать ожидание снятия блокировки. Аналогичная ситуация происходит с t2: он пытается получить блокировку s1, все еще удерживая блокировку s2. Поскольку блокировка s1 удерживается t1, t2 также будет блокироваться. Это приводит к тупику.

Чтобы исправить это, оба потока должны использовать только одну блокировку для синхронизации своей работы. Возможное решение:

class Shared
{
    private static final Object LOCK = new Object();

    // first synchronized method
    void test1(Shared s2)
    {
        synchronized (LOCK) {
            System.out.println("test1-begin");
            Util.sleep(1000);

            // taking object lock of s2 enters
            // into test2 method
            s2.test2(this);
            System.out.println("test1-end");
        }
    }

    // second synchronized method
    void test2(Shared s1)
    {
        synchronized (LOCK) {
            System.out.println("test2-begin");
            Util.sleep(1000);

            // taking object lock of s1 enters
            // into test1 method
            s1.test1(this);
            System.out.println("test2-end");
        }
    }
}

Это исправит тупик. Однако, учитывая текущую реализацию, это приведет к бесконечному циклу, вызванному косвенной рекурсией: s1.test1(s2) -> s2.test2(s1) -> s1.test1(s2) -> s2.test2(s1) -> ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...