Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

visibility of side effects when creating and joining threads

When are writes that are performed by one thread visible to a different thread when there are no synchronized blocks and no volatile variables? Here is a simplified quicksort example:

int middle = partitionForTheFirstTime(array);

Thread t = new Thread(new Quicksorter(array, 0, middle - 1));
Thread u = new Thread(new Quicksorter(array, middle + 1, array.size - 1));

t.start()
u.start();

t.join();
u.join();

(For the sake of simplicity, assume that the two "worker threads" do not spawn any additional threads.)

Does joining with the two threads guarantee that the current thread sees all their side effects?


On a related note, what would happen if I created the threads before the initial partitioning?

Quicksorter a = new Quicksorter();
Quicksorter b = new Quicksorter();

Thread t = new Thread(a);
Thread u = new Thread(b);

int middle = partitionForTheFirstTime(array);

a.setParameters(array, 0, middle - 1);
b.setParameters(array, middle + 1, array.size - 1);

t.start()
u.start();

t.join();
u.join();

Will the two threads be able to see the side effects caused by partitionForTheFirstTime()? In other words, does creating a Thread incur a happens-before relationship, or does starting a Thread?

like image 570
fredoverflow Avatar asked Feb 23 '23 23:02

fredoverflow


1 Answers

From section 17.4.5 of the JLS:

It follows from the above definitions that:

  • An unlock on a monitor happens-before every subsequent lock on that monitor.
  • A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
  • A call to start() on a thread happens-before any actions in the started thread.
  • All actions in a thread happen-before any other thread successfully returns from a join() on that thread.
  • The default initialization of any object happens-before any other actions (other than default-writes) of a program.

The bits about start() and join() are the relevant ones for you - in other words, when you've join()-ed a thread successfully, you see all actions in that thread. If you start() a thread, that new thread will see all the actions which have already occurred in the thread which calls start().

EDIT: Also see "memory consistency errors".

like image 113
Jon Skeet Avatar answered Mar 07 '23 01:03

Jon Skeet