Can problems arise when using the object of the next class in several parallel threads? If so, how best to fix?

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 = ... } } 

    2 answers 2

    The problem may be with the isCorrect method

    The case is as follows: Let there be flow A and flow B working with this object, isCorrect is simultaneously called in both flows, further:

     if(!correct){ //correct == false для потока А и для потока Б //Оба потока попадают сюда, и оба попадут внутрь computeCorrectness, но по очереди. //Я полагаю что этот метод должен выполниться только в одном из потоков. computeCorrectness(); } 

    To solve this problem, I recommend to get acquainted with the Double checked locking pattern.

    • Can you please explain how in my case this pattern can be used? Thank. - Alexander Dermenzhi
    • private volatile boolean correct; public booolean isCorrect(){ if (!correct){ synchronezed (this){ if (!correct){ computeCorrectess(); }} } return correct; } private volatile boolean correct; public booolean isCorrect(){ if (!correct){ synchronezed (this){ if (!correct){ computeCorrectess(); }} } return correct; } Remove sync from computeCorrectess ()? - Alexander Dermenzhi
    • That's right with you. If computeCorrectness is not planned to be used anywhere else and it will be encapsulated, then synchronization can be removed. You can play around with the verification code from the PeterSlusar answer in order to verify that everything is in order. - iksuy

    The problem will be with the isCorrect method and to be perfectly accurate with the synchronization of the private synchronized method of the computeCorrectess ()

    All streams that have reached this method will be in a queue after passing a logical fork:

     if (!correct) { } 

    and as it is further understood, the first incoming stream will change the state of the flag, but a queue of threads may already be formed. Verification code:

     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; } } } 

    recommend reading