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

fre*_*low 4 java concurrency multithreading synchronization memory-model

当没有同步块且没有volatile变量时,由一个线程执行的写入何时对另一个线程可见?这是一个简化的快速排序示例:

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();
Run Code Online (Sandbox Code Playgroud)

(为简单起见,假设两个"工作线程"不会产生任何额外的线程.)

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


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

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();
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 8

JLS第17.4.5节开始:

根据上述定义,可以得出:

  • 监视器上的解锁发生在该监视器上的每个后续锁定之前.
  • 写入易失性字段(第8.3.1.4节) - 在每次后续读取该字段之前发生.
  • 在启动线程中的任何操作之前,对线程的start()调用发生.
  • 线程中的所有操作都发生在任何其他线程从该线程上的join()成功返回之前.
  • 任何对象的默认初始化发生在程序的任何其他操作(默认写入除外)之前.

关于start()join()你的相关内容 - 换句话说,当你join()成功地创建一个线程时,你会看到该线程中的所有动作.如果你start()是一个线程,那个新线程将会看到调用的线程中已经发生的所有操作start().

编辑:另请参阅"内存一致性错误".