2016-10-08 4 views
1

Для создания взаимоблокировки между двумя потоками путем доступа к методу печати в потоки. Я использовал циклический барьер, чтобы оба потока запускались в одно и то же время. Если я прав, мой метод печати не занимает много времени, поэтому он разделяется двумя потоками и не вызывает Deadlock.Попытка создать тупик между двумя потоками

import java.util.concurrent.BrokenBarrierException; 
import java.util.concurrent.CyclicBarrier; 

public class TWOTHREADDEADLOCLK { 

    static int b =0; 
    synchronized static void print() 
    { 

     System.out.println(Thread.currentThread().getName() + "  " + b); 
    } 
    synchronized static int getb() 
    { 
     print(); 
     return b; 
    } 

    synchronized static void updateb() 
    { 
     print(); 
     b=b+10; 
    } 
    public static void main(String[] args) { 

     final CyclicBarrier bar = new CyclicBarrier(2); 
     Thread thread1 = new Thread(new Runnable(){ 

      @Override 
      public void run() 
      { 
       try { 
        bar.await(); 

        Thread.sleep(10000); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       catch (BrokenBarrierException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       System.out.println(Thread.currentThread().getName()); 
       while(true) 
        print(); 

      } 

     }); 
     Thread thread2 = new Thread(new Runnable(){ 

      @Override 
      public void run() 
      {try { 
       bar.await(); 
      } catch (InterruptedException | BrokenBarrierException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      System.out.println(Thread.currentThread().getName()); 
      while(true) 
       getb(); 

      } 

     }); 
     thread1.start(); 
     thread2.start(); 
    } 
} 

ответ

5

Вы не можете создать тупик с одним барьером. Идея тупика состоит в том, чтобы иметь (по крайней мере) два потока, каждый из которых имеет разный замок и пытается запереть другой. НАПРИМЕР, рассмотрим этот простой пример:

public class TwoLockRunnable implements Runnable { 

    private Lock lockInConstructor; 
    private Lock lockInRuntime; 

    public TwoLockThread(Lock lockInConstructor, Lock lockInRuntime) { 
     this.lockInConstructor = lockInConstructor; 
     this.lockInRuntime = lockInRuntime; 

     this.lockInConstructor.lock(); 
    } 

    @Override 
    public void run() { 
     lockInRuntime.lock(); 

     System.out.println("After the lock in run()"); 
    } 

    public static void main(String[] args) { 
     Lock lock1 = new ReentrantLock(); 
     Lock lock2 = new ReentrantLock(); 

     TwoLockRunnable runnable1 = new TwoLockThread(lock1, lock2); 
     TwoLockRunnable runnable2 = new TwoLockThread(lock2, lock1); 

     new Thread(runnable1).start(); 
     new Thread(runnable2).start(); 
    } 
} 

Первый поток замков lock1 в своем конструкторе и второй замки lock2 в своем конструкторе. Затем первый поток пытается заблокировать lock2 при его запуске, но он не может, так как блокировка удерживается другим потоком. Аналогично, второй поток пытается заблокировать lock1 при его запуске и по той же причине не работает. Таким образом, вы получаете тупик, и сообщение "After the lock in run()" никогда не печатается.

2

как Mureinik, это является 'синхронизированы' демо:

public class DeadLockAATest { 

static void methodA(DeadLockAATest d1, DeadLockAATest d2) { 
    synchronized (d1) { 
     try { 
      Thread.sleep(10); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     synchronized (d2) { 
      System.out.println("\t\t\tmethodA:" + Thread.currentThread().getName()); 
     } 
    } 
} 

public static void main(String[] args) { 
    DeadLockAATest d1 = new DeadLockAATest(), d2 = new DeadLockAATest(); 
    Thread t1 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      System.out.println("t1-start:" + Thread.currentThread().getName()); 
      methodA(d1, d2); 
      System.out.println("t1-end:" + Thread.currentThread().getName()); 
     } 
    }); 
    Thread t2 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      System.out.println("t2-start:" + Thread.currentThread().getName()); 
      methodA(d2, d1); 
      System.out.println("t2-end:" + Thread.currentThread().getName()); 
     } 
    }); 
    t1.start(); 
    t2.start(); 
    System.out.println("deadlock..."); 
} 

}

выход тупиковой (только один contion, может быть, t2 начинается первый):

t1-start:Thread-0 
deadlock... 
t2-start:Thread-1 

вы можете заменить

методA (d2, d1);

к

Methoda (d1, d2);

и это будет выход:

t1-start:Thread-0 
t2-start:Thread-1 
deadlock... 
      methodA:Thread-0 
t1-end:Thread-0 
      methodA:Thread-1 
t2-end:Thread-1 

и это не тупик, надеюсь, чтобы помочь вам.