4

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

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()吗?换句话说,创建线程是否会产生先发生关系,还是启动线程?

4

2 回答 2

8

JLS 的第 17.4.5 节

从上面的定义可以得出:

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

与您相关的部分start()join()相关部分 - 换句话说,当您join()成功编辑线程时,您会看到该线程中的所有操作。如果您start()是一个线程,则该新线程将看到调用的线程中已经发生的所有操作start()

编辑:另见“内存一致性错误”

于 2011-06-07T10:23:32.607 回答
0

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

于 2011-06-07T11:03:14.727 回答