Многопотоковый доступ к переменной внутри функции - PullRequest
2 голосов
/ 24 декабря 2009

У меня есть функция, которая запускает пару потоков (это тестовая функция), и один из потоков изменяет состояние переменной. Поскольку локальные переменные не могут быть помечены как volatile, я предполагаю, что несколько потоков в этом методе всегда будут иметь обновленное состояние переменной. Это правильно? Вот пример кода

public void someMethod() {
   MutableBoolean mb = new MutableBoolean(false);
   Thread t1 = new Thread() {
       public void run() {
           while (someCondition) {
              if ( mb.getValue() ) {
                 ...do something
              }
           }
       }  
   }
   t1.start();

   Thread t2 = new Thread() {
         public void run() {
             if ( someCondition ) {
                mb.setValue(true);
             }
         }
   }
   t2.start();  

   ...wait for the threads to complete

}

Ответы [ 4 ]

6 голосов
/ 24 декабря 2009

Если MutableBoolean не использует блокировку в своих методах set / get value или не является атомарной операцией, тогда это не потокобезопасно.

getValue может считывать значение, пока setValue обновляет его. Вы можете сойти с этим с логическим значением, но для любого более сложного типа это, вероятно, потерпит неудачу.

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

0 голосов
/ 24 декабря 2009

Предыдущие постеры верны, что этот код не скомпилируется без завершения mb final. Для ссылочных типов final означает, что вы не можете изменить объект, на который ссылается переменная. не означает, что вы не можете изменить состояние этого объекта. Таким образом, вы не можете заставить mb ссылаться на другой экземпляр MutableBoolean , но setValue (...) будет вести себя как всегда. MutableBoolean.getValue () и MutableBoolean.setValue (...) должны быть синхронизированы, чтобы один поток мог видеть изменения друг друга.

Обратите внимание, что нет гарантии того, в каком порядке будут выполняться операторы в двух новых потоках. Вначале может выполняться либо t2, либо t1, либо инструкции могут чередоваться.

Ничто из этого не зависит от того факта, что mb является локальной переменной, за исключением требования, чтобы она была окончательной.

См. Параллелизм Java на практике для окончательного слова по этой теме.

0 голосов
/ 24 декабря 2009

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

Ваш вопрос не о состоянии самого объекта mb (значений, хранящихся в полях объекта MutableBoolean). Для этих полей вы можете использовать изменчивые и / или синхронизированные методы для обеспечения безопасности потока.

0 голосов
/ 24 декабря 2009

Чтобы иметь видимость между нитями, volatile - не единственная опция. Любая синхронизация (блокировка) также будет работать.

В этом случае MutableBoolean может быть потокобезопасным классом, так что он сделает эту работу.


Как сказал Данбен, MutableBoolean может потребоваться final для передачи в функции.

Тестировали ли вы свой код в IDE перед публикацией?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...