#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; } } } рекомендую к прочтению
Комментариев нет:
Отправить комментарий