Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Несколько параллельных потоков, будут ли проблемы

#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; } } } рекомендую к прочтению

Комментариев нет:

Отправить комментарий