2015-02-19 5 views
2

Возможно ли, что это симуляция сценария скрытой блокировки Java только с одним объектом, разделенным между несколькими потоками?Имитация мертвой блокировки Java-потока

Например, у меня есть класс

public class MyClass { 

    public synchronized void syncInstanceMethod1(){ 
     /// Anything here to simulate a dead lock 

    } 
    public synchronized void syncInstanceMethod2(){ 
     /// Anything here to simulate a dead lock 
    } 
    public static synchronized void syncStaticMethod1(){ 
     /// Anything here to simulate a dead lock 
    } 
    public static synchronized void syncStaticMethod2(){ 
     /// Anything here to simulate a dead lock 
    } 

    public void instanceMethod1(){ 
     /// Anything here to simulate a dead lock 
    } 

    public void instanceMethod2(){ 
     /// Anything here to simulate a dead lock 
    } 


    public static void main(String[] args) { 
     MyClass shared = new MyClass(); // Allowed to create only one instance 

     Thread t1 = new Thread(new Runnable() { 
      @Override 
      public void run() { 

       // Do whatever here to simulate dead lock like calling various methods on the shared object in any order 

      } 
     }); 

     Thread t2 = new Thread(new Runnable() { 
      @Override 
      public void run() { 

       // Do whatever here to simulate dead lock like calling various methods on the shared object in any order 

      } 
     }); 

     // Allowed to create more threads like above. t3 , t4 etc... 

     t1.start(); 
     t2.start(); 
    } 

} 

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

Мы можем смоделировать эту ситуацию из одного из синхронных методов экземпляра, вызвав статический синхронизированный метод, пытаясь заблокировать объект класса, удерживая блокировку на «этом». Но для возникновения тупика нам нужна аналогичная ситуация в обратном порядке в другом месте.

Кроме того, поскольку статический метод не может получить доступ к «этому», он не может блокировать это «и», и два метода синхронизированного экземпляра не могут работать одновременно, эти вещи полагают, что мы не можем имитировать мертвую блокировку здесь. Я прав?

+0

Статический метод может получить доступ к 'this' в виде статической переменной (по аналогии с одноплодной шаблон). – MeetTitan

ответ

2

Хотя вас попросили создать только один экземпляр, в потоках по-прежнему есть два замка. Методы экземпляров требуют, чтобы поток получал блокировку на объекте объекта MyClass, то есть shared или this в зависимости от того, как вы на него смотрите.

Статические методы, с другой стороны, потребовали бы, чтобы поток приобрел блокировку на MyClass.classкласс экземпляр объекта; тот, который вы получаете от this.getClass().

Итак, если Thread A уже выполняет синхронизированный метод экземпляра (имеет блокировку по this) и пытается войти в один из синхронизированных статических методов, тогда как другой поток B также выполняет статический метод (имеет блокировку на MyClass.class) и теперь пытается ввести синхронный метод экземпляра на том же объектеMyClass, произойдет взаимоблокировка.

Вот код, который имитирует этот сценарий.

public class SingleObjectDeadlock { 

    public synchronized void syncInstanceMethod1() { 
     System.out.println("In syncInstanceMethod1()"); 
     syncStaticMethod2(); 
    } 

    public synchronized void syncInstanceMethod2() { 
     System.out.println("In syncInstanceMethod2()"); 
    } 

    public static synchronized void syncStaticMethod1(SingleObjectDeadlock shared) { 
     System.out.println("In syncStaticMethod1()"); 
     shared.syncInstanceMethod2(); 
    } 

    public static synchronized void syncStaticMethod2() { 
     System.out.println("In syncStaticMethod2()"); 
    } 

    public static void main(String[] args) { 
     SingleObjectDeadlock shared = new SingleObjectDeadlock(); 

     Thread t1 = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       shared.syncInstanceMethod1(); 
      } 
     }); 

     Thread t2 = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       SingleObjectDeadlock.syncStaticMethod1(shared); 
      } 
     }); 

     t1.start(); 
     t2.start(); 

     System.out.println("DEADLOCK!"); 
    } 
} 

После запуска вы увидите, что тупиковый происходит и программа никогда не печатает

In syncStaticMethod2() 
In syncInstanceMethod2() 
1

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

Я думаю, что я не знаю, что разрешено в вашем задании, но это немного запутанно.

+0

Вы предлагаете изменить подпись синхронизированного статического метода, чтобы принять экземпляр MyClass (shared) в качестве аргумента? – gipsy

+1

@gipsy Я неправильно прочитал ваш вопрос, когда впервые прочитал его. Но если общий экземпляр не входит в область вашего статического синхронизированного метода (например, ссылку со статической переменной), то вы не сможете блокировать сначала статическую, а затем в общем экземпляре, поскольку это не в области видимости, может 't заблокировать или вызвать его. Наверное, я не знаю, что разрешено в вашем задании, но это немного запутанно. – NESPowerGlove

+0

Ваш ответ указал мне на правильное решение.Но я принимаю ответ Рави Таплияля, поскольку он собирается помочь другим. – gipsy

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