Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to use an object in different threads, but NOT at the same time?

I've read everywhere that if a field is used at the same time by different threads, some sort of synchronization is needed, and that if it is used by only one thread, it's not needed. But what if it's used by different threads, but not at the same time ? Let's take a code like this:

Thing thing = new Thing();
Thread t1 = new Thread(new MyRunnable(thing));
Thread t2 = new Thread(new MyRunnable(thing));
t1.start();
t1.join();//Wait for t1 to finish
t2.start();

MyRunnable is:

class MyRunnable implements Runnable {
    //skipped constructor and field "private final Thing thing"
    public void run() {
        thing.someUpdate();
    }
}

Is it safe? Are all the updates made by t1 visible by t2?

like image 862
ElectronWill Avatar asked Mar 28 '16 23:03

ElectronWill


2 Answers

In this case then the changes are visible because Thread.join and Thread.start creates happens-before relationships between the actions in both threads. See Memory Consistency Errors:

  • When a statement invokes Thread.start, every statement that has a happens-before relationship with that statement also has a happens-before relationship with every statement executed by the new thread. The effects of the code that led up to the creation of the new thread are visible to the new thread.

  • When a thread terminates and causes a Thread.join in another thread to return, then all the statements executed by the terminated thread have a happens-before relationship with all the statements following the successful join. The effects of the code in the thread are now visible to the thread that performed the join.

If you weren't using these methods in that order, then the changes may not be visible. The threads don't need to be running at the same time to cause an issue because values can be cached within a thread or some optimization could occur etc.

like image 108
fgb Avatar answered Oct 25 '22 00:10

fgb


I think the question is too abstract. General answer to question "Are all the updates made by t1 visible by t2?" is "Yes". But they will be visible only because of the way you run the threads. Threads in your example are not parallel. So, yes, in this example, fields of MyRunnable will be visible for both threads. But MyRunnable class itself is not thread-safe. If it will be used with concurrent threads you will probably get troubles. It depends on details of MyRunnable.someUpdate(). You should use "volatile" keyword for your fields, "java.util.concurrent.*" classes or any of synchronisation mechanisms if it's necessary. Maybe this documentation will help to start: https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

like image 24
Andrej Istomin Avatar answered Oct 24 '22 23:10

Andrej Istomin