Java 调用Thread.start()时,是否在可传递之前发生?
假设我们有一节课Java 调用Thread.start()时,是否在可传递之前发生?,java,multithreading,concurrency,visibility,safe-publication,Java,Multithreading,Concurrency,Visibility,Safe Publication,假设我们有一节课 class Foo { int x; Foo() { x = 5; } } 还有一些客户端代码 public static void main(String[] args) { Foo foo = new Foo(); new Thread(() -> { while (true) { new Thread(() -> { if (foo
class Foo {
int x;
Foo() {
x = 5;
}
}
还有一些客户端代码
public static void main(String[] args) {
Foo foo = new Foo();
new Thread(() -> {
while (true) {
new Thread(() -> {
if (foo.x != 5) {
throw new AssertionError("this statement is false 1");
}
new Thread(() -> {
if (foo.x != 5) {
throw new AssertionError("this statement is false 2");
}
}).start();
}).start();
}
}).start();
}
是否因为之前发生的事件是可传递的,所以不可能抛出断言错误
尽管Foo的x不是最终的,但由于Thread.start()的before保证,从实例化Foo的线程新创建的线程将看到调用Thread.start()之前的所有更新
但是,此线程也会产生许多子线程,并且由于再次存在“发生在之前”关系,我们是否可以说,由于“发生在之前”的可传递属性,该断言错误永远不会被抛出?您的问题:
既然又有一段“先发生后发生”的关系,我们能这么说吗
由于之前发生的事件具有传递性,所以
断言错误永远不会被抛出
答案是肯定的。正如我们在下面的例子中所看到的:
- 如果hb(x,y)和hb(y,z),那么hb(x,z)
- 对线程的
调用发生在已启动线程中的任何操作之前start()
- hb(
,第一个线程中的第一个操作)和new Foo()
- hb(第一个线程中的第一个操作,第一个断言线程中的第一个操作)
- hb(第一个线程中的第一个操作,第二个断言线程中的第一个操作)
- hb(
,第一个断言线程中的第一个操作)newfoo()
- hb(
,第二个断言线程中的第一个操作)newfoo()
(由于“对于每个线程t,t中同步操作(§17.4.2)的同步顺序与t的程序顺序(§17.4.3)一致”,我可以省略中间的步骤,如
while(true)
循环)beautiful!这如果hb(x,y)和hb(y,z),那么hb(x,z)
实际上解释了这一点。1+顺便说一句,当您引用JLS时,再次阅读答案“(因为“对于每个线程……可以省略中间的步骤,如while(true)循环)”,我认为,当您有一些同步操作,例如thread.start(),那么这些事情就不能重新排序,所以逻辑上应该首先出现的所有事情单个线程中的(无论是上面的行还是从右向左计算的行)都将运行,例如Foo x=new Foo();new thread(()->{}).start();new thread(()->{}).start();Foo总是在下两个线程以及Runnable之前首先计算lambda@katiex7-允许编译器对任一线程中的指令重新排序,但这不会影响该线程的独立执行。JLS 17.4.内存模型执行构造调用x=5;
hbFoo-Foo=new-Foo()
。?