2015-03-17 2 views
1

здесь кодКод java для ситуации взаимоблокировки?

public class TestDeadlockExample1 { 
    public static void main(String[] args) { 
      final String resource1 = "xyz"; 
      final String resource2 = "pqr"; 
      // t1 tries to lock resource1 then resource2 
      Thread t1 = new Thread() { 
       public void run() { 
        synchronized (resource1) { 
        System.out.println("Thread 1: locked resource 1"); 

        try { Thread.sleep(10000);} catch (Exception e) {} 

        synchronized (resource2) { 
        System.out.println("Thread 1: locked resource 2"); 
        } 
       } 
       } 
      }; 

      // t2 tries to lock resource2 then resource1 
      Thread t2 = new Thread() { 
       public void run() { 
       synchronized (resource2) { 
        System.out.println("Thread 2: locked resource 2"); 

        try { Thread.sleep(10000);} catch (Exception e) {} 

        synchronized (resource1) { 
        System.out.println("Thread 2: locked resource 1"); 
        } 
       } 
       } 
      }; 


      t1.start(); 
      t2.start(); 
      System.out.println("completed"); 
      } 
} 


here 

t1.start(); 
t2.start(); 
System.out.println("completed"); 

здесь

в этом t1.start() и t2.start() записываются в последовательном порядке, поэтому мои сомнения в том, что как нить начинается в том же или а не или t1 запускается, тогда он приходит к t2 и выполняет, если это правильно, как это становится ситуацией с блокировкой. Я хочу знать выполнение этих потоков.

+0

Почему вы блокируете ресурсы того же порядка? –

+0

На самом деле я искал тупик ситуации, и я закончил с этим кодом .. но исполнение я не понял –

ответ

0

Я узнал, что для предотвращения взаимоблокировок вам необходимо чтобы сделать блок synchronized неизменно одинаковым.

  public void run() { 
       synchronized (resource1) { 
       synchronized (resource2) { 
       System.out.println("Thread 1: locked resource 1"); 
       System.out.println("Thread 1: locked resource 2"); 
       try { Thread.sleep(10000);} catch (Exception e) {} 
       } 
      } 
      } 

и

 Thread t2 = new Thread() { 
      public void run() { 
      synchronized (resource1) { 
      synchronized (resource2) { 
       System.out.println("Thread 2: locked resource 2"); 
       System.out.println("Thread 2: locked resource 1"); 
       try { Thread.sleep(10000);} catch (Exception e) {} 
       } 
      } 
      } 
     }; 
0

в этом t1.start() и t2.start() записываются в последовательном порядке, так мои сомнения в том, что как нить начинается в том же или не или t1 начинается, выполняет затем приходит к t2 и выполняет

вызов start() не гарантирует, что тема начинается немедленно. Нативный вызов выполняется через start0(), который inturn вызывает ОС для разветвления потока. Итак, в основном, thread2 может начинаться до thread1. У вас нет контроля над тем, какой поток запускается первым.

, как это становится тупиковой ситуации

Существует вероятность тупика здесь, потому что t1 может получить блокировку на resource1 и t2 может получить блокировку на resource2 в то же время. Теперь оба потока хотят, чтобы ресурс удерживался другим потоком. Следовательно, у вас есть тупик.

Так как стандартная практика, как t1 и t2 должны приобрести замок в же последовательности.

+0

, поэтому мы не можем предсказать, какой поток будет запущен, может быть t2 начинается, а t1 начинается позже или t1 начинается, а t2 начинается позже или оба запускаются одновременно ... но если время сна слишком короткое, я имею в виду сон (1); то ресурс может освободиться и избежать ситуации с мертвой блокировкой. Также мы не можем подтвердить, что этот код каждый раз переходит в тупик. –

+0

@ vineeth.soman - Мы не можем подтвердить, что ситуация в тупике случится. ОС имеет механизмы предотвращения блокировки и разрешения. Чтобы добавить к этому 'sleep (1)', очень мало на современных компьютерах. На самом деле это может быть проигнорировано. Да, мы не можем предсказать, какая нить начинается сначала. Также не гарантируется, что начальный поток сначала получит блокировку: P .. – TheLostMind

0

sleep() гарантирует, что оба t1 и t2 приобретут свой первый замок до того, как они перейдут к их второй блокировке. Независимо от того, какой поток работает первым.

+0

Я думаю, что * длина *, для которой нить * спит *, здесь важна. В его текущем коде 'sleep (10000)' достаточно, чтобы обеспечить описанное вами поведение, но если продолжительность сна короче, один поток может сначала получить обе блокировки – TheLostMind

0

Когда вы запускаете свою программу java, JRE запускает основной поток и этот основной поток выполняет ваш метод main.

Когда вы вызываете t1.start(), новая ветка порождает и запускает метод run первого анонимного класса. С этого момента в вашей программе одновременно выполняются 2 потока: «основной поток» и «поток 1».

Когда вы вызываете t2.start(), другой поток генерирует и выполняет второй метод анонимного класса run. С этого момента в вашей программе одновременно выполняются 3 потока: «основной поток», «поток 1», «поток 2».

Порядок, в котором выполняются потоки, не определен. Это может быть что угодно. Обычно они выполняются одновременно.

Ваши «резьба 1» и «резьба 2» получают блокировки на resource1 и resource2 соответственно и спать в течение 10 секунд. Хотя это происходит, ваш «основной» поток заканчивает выполнение. Но в вашей программе есть еще 2 потока, поэтому пока метод main закончен, программа еще не закончена.

После спящих ваших «ниток 1» и «ниток 2», пытающихся приобрести замки на resource 2 и resource 1, но эти замки уже приобретены, поэтому они будут ждать, пока держатель замка не отпустит его. Держатель замка никогда не выпустит его, так как он ждет другого ресурса, поэтому эта программа никогда не остановится. Это классическая тупиковая ситуация.

0

«так мои сомнения в том, что как нить начинается в то же или нет, или t1 начинается, выполняет затем приходит к t2 и выполняет»

Просто потому, что t1 нити и t2 порождаются последовательно, не означает, что они выполняются последовательно. Резьбы используются для параллельного выполнения единиц работы.

Благодаря метод сна вызывает в вашем коде, это тупик, потому что

  1. t1 приобретает R1 или t2 приобретает t2. Порядок неопределен.

  2. Оба потока спать в течение 10 секунд после получения их соответствующего ресурса, поэтому мы можем с высокой степенью уверенности сказать в этом примере, что оба потока приобрели ресурсы в какой-то момент во время периода сна Другие.

  3. Когда t1 или t2 просыпаются и пытаются получить второй ресурс, который уже удерживается соответствующими дочерними ветвями, он будет блокироваться. Оба потока будут блокировать попытку приобретения ресурса, принадлежащего другому.

Этот сценарий возникает только потому, что потоки выполняются параллельно, а не последовательно.

Пожалуйста, см http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

0

Порядок выполнения потока не определен.

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

Thread t2 = new Thread() { 
    public void run() { 
    synchronized (resource1) { 
     System.out.println("Thread 2: locked resource 2"); 

     try { Thread.sleep(10000);} catch (Exception e) {} 
     System.out.println("Thread 2: Waiting for resource 1..."); 
     synchronized (resource2) { 
     System.out.println("Thread 2: locked resource 1 and 2"); 
     } 
    } 
    } 
}; 
Смежные вопросы