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?


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".


    Unless you execute start() prior executing partitionForTheFirstTime() both threads will operate on the same data. But you need to be carefull in terms of passing referential values to these separate threads in this example the array value is passed by reference in opposite to primitive values which are passed by value. As a result both threads will operate on the very same table and this may cause race conditions

    链接地址: http://www.djcxy.com/p/50182.html

    上一篇: 为什么所有Future.get()在invokeAll中抛出CancelleationException超时

    下一篇: 创建和连接线程时的副作用的可见性