Java тупиковая провокация - PullRequest
0 голосов
/ 19 июля 2009

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

class Resource {

    public Integer value = 42;
}

public class DeadLockRisk implements Runnable {

    private Resource resourceA = new Resource();
    private Resource resourceB = new Resource();

    public void write(int a, int b) {

        System.out.println(Thread.currentThread().getName() + " try write Lock A");

        synchronized(resourceA) {

            System.out.println(Thread.currentThread().getName() + " write Lock A");
            System.out.println(Thread.currentThread().getName() + " try write Lock B");

            synchronized(resourceB) {

                System.out.println(Thread.currentThread().getName() + " write Lock B");

                resourceA.value = a;
                resourceB.value = b;
        //sit on it!
        //try { Thread.sleep(5000); } catch (Exception e) {}

        System.out.println(Thread.currentThread().getName() + " release write B");
        }
        System.out.println(Thread.currentThread().getName() + " release write A");
    }
    }

    public int read() {

    Integer retVal;
        System.out.println(Thread.currentThread().getName() + " try read Lock B");

        synchronized(resourceB) {

            System.out.println(Thread.currentThread().getName() + " read Lock B");
            System.out.println(Thread.currentThread().getName() + " try read Lock A");

            synchronized(resourceA) {

                System.out.println(Thread.currentThread().getName() + " read Lock A");
                retVal = resourceB.value + resourceA.value;
        System.out.println(Thread.currentThread().getName() + " release read A");
            }
        System.out.println(Thread.currentThread().getName() + " release read B");
        }
    return retVal;
    }

    public void run() {


    if (Thread.currentThread().getName().equals("Thread-1")) {
        write(1,2);
    }

    System.out.println(read());
    }

    public static void main(String[] args) {

        Thread ta = new Thread(new DeadLockRisk());
        Thread tb = new Thread(new DeadLockRisk());
        ta.start(); tb.start();
    }
}

(javac-версия javac 1.6.0_0 uname -a Linux inspiron 2.6.29 # 1 SMP Sat 16 мая 10:56:17 CEST 2009 i686 GNU / Linux)

и получите (среди прочих ситуаций) вывод ниже:

Thread-1 try write Lock A
Thread-0 try read Lock B
Thread-1 write Lock A      <=====
Thread-0 read Lock B
Thread-1 try write Lock B
Thread-0 try read Lock A
Thread-1 write Lock B
Thread-0 read Lock A       <=====
Thread-1 release write B
Thread-0 release read A
Thread-1 release write A
Thread-0 release read B
Thread-1 try read Lock B
154
Thread-1 read Lock B
Thread-1 try read Lock A
Thread-1 read Lock A
Thread-1 release read A
Thread-1 release read B
3

Что я вижу не так? Как Thread-0 может даже войти в критическую секцию в read () и получить блокировку на A, прежде чем блокировка будет снята Thread-1. Это возможно, потому что вывод не является синхронным? С этим кодом тупик не возникает.

Ответы [ 2 ]

5 голосов
/ 19 июля 2009

Вы передаете разные экземпляры DeadLockRisk в оба потока, чтобы они не синхронизировались на одних и тех же объектах.

1 голос
/ 19 июля 2009

Оба экземпляра DeadlockRisk имеют разные экземпляры для полей resourceA и resourceB. Если вы хотите, чтобы код работал так, как вы ожидаете, измените поля экземпляра на статические поля.

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