当没有同步块且没有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();
(为简单起见,假设两个“工作线程”不会产生任何额外的线程。)
加入两个线程是否可以保证当前线程看到所有副作用?
在相关的说明中,如果我在初始分区之前创建了线程会发生什么?
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()
引起的副作用?换句话说,创建一个线程会产生一个先发生过的关系,还是开始一个线程?
答案 0 :(得分:8)
从以上定义得出:
- 监视器上的解锁发生在该监视器上的每次后续锁定之前。
- 在对该字段的每次后续读取之前发生对易失性字段(第8.3.1.4节)的写入。
- 在启动线程中的任何操作之前,对线程的start()调用发生。
- 线程中的所有操作都发生在任何其他线程从该线程上的join()成功返回之前。
- 任何对象的默认初始化发生在程序的任何其他操作(默认写入除外)之前。
关于start()
和join()
的相关内容与您相关 - 换句话说,当您join()
成功编写线程时,您会看到该主题中的所有操作。如果你start()
一个线程,那个新线程将会看到调用start()
的线程中已经发生的所有操作。
答案 1 :(得分:0)
除非在执行partitionForTheFirstTime()之前执行start(),否则两个线程将对相同的数据进行操作。但是,在将参考值传递给这些单独的线程时,您需要小心谨慎,在此示例中,数组值通过引用传递给与值传递的原始值相反。因此,两个线程都将在同一个表上运行,这可能会导致竞争条件