2014-07-21 3 views
1

Я пытаюсь иметь Резьба2 ждать строк и Резьба1 уведомить об обновлении Струнного, я синхронизировать объект String, как код ниже показывает, но я все еще получаю IllegalMonitorStateException Вот мой кодJava синхронизируется Строка IllegalMonitorStateException

public class Class1{ 

String string = ""; 

public Class1(){ 


    Thread t1 = new Thread(){ 

     public void run(){ 

      synchronized(string){ 

       string = "Something"; string.notifyAll(); //This is the line that throws an IllegalMonitorStateException 
      } 

     } 

    }; 


    Thread t2 = new Thread(){ 

     public void run(){ 

      synchronized(string){ 

       try{ 

        string.wait(); 

       }catch(Exception e){ 

        e.printStackTrace(); 

       } 

      } 

     } 

    }; 

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

} 

Там нет ничего, кроме StackTrace подсветки string.notifyAll()

+1

Я не получаю 'IllegalMonitorStateException'. – Braj

+0

Когда вы говорите об «обновлении строки», нужно предположить, что * экземпляр *, который представлен переменной 'string', изменяется (и, конечно, код, который вы указали, - это * не * код, вызывающий ошибка) – Marco13

+0

@Braj Я полагал, что это может быть проблема BlackBerry @ Marco13 да Я меняю значение 'string' – s3nzoM

ответ

3
  1. Ваш код содержит гонки данных, поскольку он обращается к изменяемый string переменной за пределами synchronized блока. В частности, это происходит на линии synchronized(string). При разыменовании string для достижения объекта, чей монитор будет заблокирован, поток уже не удерживает блокировку этого объекта. Поэтому у вас нет гарантии, какой объект он получит.

  2. факт, что вы mutate переменная string означает, что она теперь указывает на какой-либо другой объект. Когда следующий поток получает блокировку на этом новом объекте, он не получит никакой пользы от какого-либо отношения происходит до, потому что это первый поток, когда-либо приобретающий блокировку на нем. Взаимное исключение также не гарантируется, потому что может быть произвольно много потоков, каждый из которых блокирует другой экземпляр String без каких-либо конфликтов.

  3. Объединение двух явлений, описанных выше, можно также видеть, что нет никакой гарантии, что объект достиг на линии synchronized(string) будет таким же, как один на один, достигнутых от в пределах синхронизированного блок. Как только это произойдет, это действительно другой объект, ваш IllegalMonitorStateException.

В общем, ситуация очень похожа на synchronized блок не существующий вообще.

Все вышеперечисленные проблемы можно избежать, если придерживаться наилучшей практики использования выделенных переменных final для обозначения объектов, используемых для блокировки. В двух словах, и исправления ошибок компиляции в вашем примере, это то, что вы должны написать:

static String string = ""; 
static final Object lock = new Object(); 

public static void main(String[] args) { 
    Thread t1 = new Thread() { 
    public void run() { 
     synchronized (lock) { 
     ... update the string variable ... 
     lock.notifyAll(); 
     } 
    } 
    }; 
    Thread t2 = new Thread() { 
    public void run() { 
     synchronized (lock) { 
     try { 
      lock.wait(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     } 
    } 
    }; 
    t2.start(); 
    t1.start(); 
} 
+0

@Downvoter Пожалуйста, оставьте комментарий, что не так с этим ответом? Можно ли улучшить? –

+0

Я не могу обновить 'final' Object – s3nzoM

+0

@meLove большая часть точки' final' - остановить вас, обновив его. Этот ответ немного вводит в заблуждение. Добавление 'final' не решает вашу проблему - ваша проблема частично решена, не обновляя переменную, которую выполняет« final ». – immibis

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