#java #многопоточность #synchronized
Могут ли возникнуть проблемы при использовании объекта следующего класса в нескольких
параллельных потоках? Если да, то как лучше исправить?
public class SomeData {
private boolean correct;
private boolean computed;
public SomeData (/*...*/){
correct = true;
computed = false;
}
public booolean isCorrect(){
if (!correct){
computeCorrectess();
}
return correct;
}
private synchronized void computeCorrectess(){
computed = true;
//some long computation of value correct
//correct = ...
}
}
Ответы
Ответ 1
Проблема может быть с методом isCorrect Кейс следующий: Пусть есть поток А и поток Б, работающие с данным объектом, в обоих потоках одновременно вызывается isCorrect, далее: if(!correct){ //correct == false для потока А и для потока Б //Оба потока попадают сюда, и оба попадут внутрь computeCorrectness, но по очереди. //Я полагаю что этот метод должен выполниться только в одном из потоков. computeCorrectness(); } Для решения данной проблемы рекомендую ознакомится с паттерном Double checked lockingОтвет 2
Проблема будет с методом isCorrect а если быть совсем точным с синхронизацией метода private synchronized void computeCorrectess() Все потоки дошедшие до данного метода станут в очередь пройдя логическую развилку: if (!correct) { } и как далее понятно первый вошедший поток изменит состояние флага но очередь потоков уже возможно будет сформирована. Проверочный код: public class SomeClass implements Runnable { SomeData someData = new SomeData(); public static void main(String[] args) { new SomeClass().threadsGenerator(); } private void threadsGenerator() { for (int i = 0; i < 10; i++) { new Thread(this).start(); } } @Override public void run() { try { someData.isCorrect(); } catch (InterruptedException e) { e.printStackTrace(); } } public class SomeData { private boolean correct; private boolean computed; public SomeData() { correct = false; computed = false; } public boolean isCorrect() throws InterruptedException { if (!correct) { computeCorrectess(); } return correct; } private synchronized void computeCorrectess() throws InterruptedException { System.out.println(correct); TimeUnit.SECONDS.sleep(1); correct = true; } } } рекомендую к прочтению
Комментариев нет:
Отправить комментарий