ElectronWill
ElectronWill

Reputation: 823

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?

Upvotes: 5

Views: 128

Answers (5)

Andrej Istomin
Andrej Istomin

Reputation: 3013

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

Upvotes: 1

fgb
fgb

Reputation: 18569

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.

Upvotes: 9

Sajeev
Sajeev

Reputation: 848

Its safe in this instance. Changes made by t1 on the thing object will be visible to t2. If there was no t1.join(); the code would not have been thread safe.

t1.start();
t1.join();//Wait for t1 to finish
t2.start();

Upvotes: 0

Sanj
Sanj

Reputation: 4029

join() method is a blocker method and waits for a thread to complete. t2 should see all updates of t1.

Upvotes: 0

Enzokie
Enzokie

Reputation: 7415

In your case it is safe since both Threads are not running on the same time.

Upvotes: 0

Related Questions