创建和连接线程时的副作用的可见性

何时是由一个线程执行的写入在不存在同步块且没有易失性变量的情况下对不同线程可见? 这是一个简化的快速排序示例:

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();

(为了简单起见,假定两个“工作线程”不会产生任何额外的线程。)

加入两个线程是否可以保证当前线程看到所有的副作用?


在相关说明中,如果在初始分区之前创建线程会发生什么情况?

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();

这两个线程是否能够看到由partitionForTheFirstTime()引起的副作用? 换句话说,创建一个线程会产生一个发生之前的关系,还是启动一个线程?


从JLS第17.4.5节开始:

从以上定义得出:

  • 监视器上的每次锁定都会在监视器上解锁。
  • 在每次后续读取该字段之前,都会发生对易失性字段(第8.3.1.4节)的写入。
  • 线程上的start()调用发生在已启动线程的任何操作之前。
  • 在任何其他线程从该线程上的join()成功返回之前,线程中的所有操作都会发生。
  • 任何对象的默认初始化发生在程序的任何其他操作(非默认写入)之前。
  • 有关start()join()的内容对你来说是相关的 - 换句话说,当你成功地join()一个线程时,你会看到该线程中的所有动作。 如果你start()了一个线程,那么这个新线程将会看到所有在调用start()的线程中已经发生的动作。

    编辑:另请参阅“内存一致性错误”。


    除非在执行partitionForTheFirstTime()之前执行start(),否则两个线程将对相同的数据进行操作。 但是在这个例子中,通过将引用值传递给这些单独的线程,您需要谨慎。数组值通过引用传递,与通过值传递的原始值相反。 结果两个线程都会在同一张桌子上运行,这可能会导致竞争状况

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

    上一篇: visibility of side effects when creating and joining threads

    下一篇: Java executors: how to be notified, without blocking, when a task completes?