2013-11-14 6 views
0

Могу ли я узнать, поддерживает ли нижеследующая программа тупик? Ниже приведены детали: Темы: process1 и process2. Объекты: сканер и принтер. процесс1 блокирует как сканер, так и принтер, но отдает сканер. Process2 блокирует сканер, но не может получить принтер, потому что process1 заблокировал его. Возможно, мои концепции потоков неясны, но могу ли я, пожалуйста, знать, где я ошибаюсь?Гарантия тупика

class DeadLock extends Thread { 

    //creating a scanner object 
    private static Object scanner = new Object(); 

    //creating a printer object 
    private static Object printer = new Object(); 

    //the process name 
    private String processName; 

    //initializes process2 is not created yet 
    private boolean process2IsCreated = false; 

    /** 
    * the constructor which sets string to process1 or 2 
    * @param string 
    */ 
    public DeadLock(String string) { 
     // TODO Auto-generated constructor stub 
     this.processName = string; 
    } 

    /** 
    * deadlock() for process1 
    */ 
    public void deadlock1() { 

     //process1 locks scanner 
     synchronized (scanner) { 

      //process1 locks printer, too 
      synchronized (printer) { 

       //create process2 after process1 
       if(process2IsCreated == false && processName.equals("process1")) { 
        new DeadLock("process2").start(); 
        process2IsCreated = true; 
       } 

       try { 
        //process1 is waiting on scanner and releases its monitor. 
        //After regaining access, process1 tries to acquire scanner 
        //but cannot do so because process2 has locked it already. 
        //. . .too late, process1! 
        scanner.wait(); 

       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 

      } 
     } 
    } 

    /** 
    * deadlock() for process2 
    */ 
    public void deadlock2() { 

     //process2 locks scanner 
     synchronized (scanner) { 

      //process2 notifies process1 which is waiting on scanner 
      scanner.notify(); 

      //process2 locks printer, but cannot lock printer because process1 has it 
      //. . .too late, process2! 
      synchronized (printer) { 
      } 
     } 
    } 

    /** 
    * both threads are scheduled to execute run() 
    */ 
    public void run() { 

     //if process1 then enter deadlock1() 
     if(processName.equals ("process1")) deadlock1(); 

     //if process 2 then enter deadlock2() 
     else deadlock2(); 
    } 

    /** 
    * the main method which creates thread process1 
    * @param a 
    */ 
    public static void main(String a[]) { 
     new DeadLock("process1").start(); 
    } 
} 
+0

В чем ваш вопрос? почему ваша программа все еще заканчивается и не заблокирована? –

+0

Вопрос в том, гарантирует ли эта программа тупик? Если нет, могу ли я получить объяснение? – user1302

ответ

2

Это, кажется, работает для меня, вот самосвала Нить в Intellij:

enter image description here

+0

Я начинаю второй поток после того, как первая нить входит в тупик1() – user1302

+0

Pardon, как вы его начинаете? В отдельном процессе? –

+0

В основном, я запускаю thread process1, чтобы начать сначала, а затем создаю thread process2 в методе deadlock1(). Сначала я запускаю процесс process1, чтобы гарантировать, что процесс thread1 запускается первым и вступает в deadlock1(), где создается следующий поток process2 и планируется выполнить run(). Это имеет смысл сейчас? – user1302

0

видеть это .. здесь вторая нить время начала

//create process2 after process1 
       if(process2IsCreated == false && processName.equals("process1")) { 
        new DeadLock("process2").start(); <---------------HERE 
        process2IsCreated = true; 
       } 
0
I guess, the flow is.. 
Thread 1 : takes scanner lock 
Thread 1: takes printer lock 
Thread 1: creates and starts 2nd thread 

Possible flow: 

Thread 2 : Starts, executes run and goes into deadlock2() 
Thread 1: waits for object scanner 
Thread 2: Enters lock Scanner 
Thread 2: Notifies lock scanner 
Thread 2: stuck as it cant get into printer block as Thread 1 has it 
Thread 1: Is waiting for Thread 2 to leave scanner block which it does not. 

Result: Thread 2 can not have Printer & Thread 1 can not start executing as Thread 2 even when it is notified scanner , has not left Scanner block. 

This is not a proper deadlock as thread 1 has not returned for execution. 
0

Прошло некоторое время с тех пор, как я использовал примитивы синхронизации Java, но для меня это выглядит так:

Thread 1 locks scanner.
Резьба 1 блокирует принтер.
Тема 2 запущена.
Тема 1 временно освобождает сканер, ожидает ожидания уведомления.
Резьба 2 замка сканера.
Тема 2 публикует уведомление.
Резьба 2 блока на принтере.

Нить 1 никогда не просыпается, потому что Thread 2 никогда не выпускает сканер.
Нить 2 никогда не просыпается, потому что нить 1 еще не выполнена с принтером.

Я предполагаю, что вы ошибаетесь в том, чтобы сделать первый сон для темы 1. Он приобрел оба ресурса, чего еще он ждет?

Существует также вероятность того, что вы используете синхронизацию; обычно достаточно простых synchronized блоков (монитора) или wait/notify вызовов (семафор). Вы используете оба.

Я думаю эмпирическое правило здесь есть «если вы собираетесь использовать wait/notify, завернуть их в минимальных synchronized блоков». Блок сканера в потоке 2 проходит через вызов notify в блок принтера.

-
Для уточнения:

synchronized (x) { A; } 
synchronized (x) { B; } 

является (использует) монитор, когда вы не хотите, А и В, чтобы выполнить одновременно.

synchronized (x) { x.wait(); } B; 
A; synchronized (x) { x.notify(); } 

использует семафор, чтобы убедиться, что A выполняется до B.

0

Да это почти идеальный пример тупиковой ситуации по следующей причине (Oracle ожидания() DOC):

Нить релизы собственности этого монитора и ждет, пока другой поток, оповещает темы, ожидающие монитор этого объекта для пробуждения [...]

Так что сканер монитора отпущен, но монитор монитора не отпущен. Вот почему вы не должны синхронизировать дважды.

Для вашего кода есть только один улов, а это spurious wakeups. Это может произойти (хотя это очень маловероятно), что звонок ожидания внезапно просыпается, никто из тех, кто звонил, не уведомлял его. Это скорее является причиной реализации блокировки в ОС, чем чем-то связанным с Java, но, работая на правильной ОС, ваш тупик может, в конце концов, проснуться через несколько дней, месяцев или лет.

Смежные вопросы