Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java op的身体。在这个粗锁之外唯一要做的事情就是创建第一个字符串值,它是您观察到的旧值_Java_Multithreading_Java.util.concurrent_Java Memory Model - Fatal编程技术网

Java op的身体。在这个粗锁之外唯一要做的事情就是创建第一个字符串值,它是您观察到的旧值

Java op的身体。在这个粗锁之外唯一要做的事情就是创建第一个字符串值,它是您观察到的旧值,java,multithreading,java.util.concurrent,java-memory-model,Java,Multithreading,Java.util.concurrent,Java Memory Model,有关JMM的更多信息,请参阅。另外,请查看最终决定可见性的变量。如果只查看volatile变量的读取和写入,则它们必须按以下顺序显示: 1 - main: read run (run is true) 2 - Thread-0: write run (run is false) 3 - main: read run (run is false) 但是控制台输出是独立的操作,不需要在读取之后立即执行。println参数的计算和方法调用不是原子的。所以我们有一些更像: 1 - main: read

有关JMM的更多信息,请参阅。另外,请查看最终决定可见性的变量。

如果只查看volatile变量的读取和写入,则它们必须按以下顺序显示:

1 - main: read run (run is true)
2 - Thread-0: write run (run is false)
3 - main: read run (run is false)
但是控制台输出是独立的操作,不需要在读取之后立即执行。println参数的计算和方法调用不是原子的。所以我们有一些更像:

1 - main: read run (run is true)
2 - main: println("Run: true")

3 - Thread-0: write run (run is false)
4 - Thread-0: println("Run: false")

5 - main: read run (run is false)
6 - main: println("Run: false")
这允许在第一次排序之后进行排序,如:

1 - main: read run (run is true)

3 - Thread-0: write run (run is false)
4 - Thread-0: println("Run: false")

2 - main: println("Run: true")

5 - main: read run (run is false)
6 - main: println("Run: false")
根据中的源代码,行:

System.out.println(Thread.currentThread().getName() + " run:" + run);
可以内联如下:

String x = Thread.currentThread().getName() + " run:" + run;
synchronized(System.out.lock) {
    System.out.print(x);
    System.out.println();
}
因此,
println
中存在同步,但不包括读取
run
。这意味着
run
的值可以在读取和输出之间更改,从而导致
run
的旧值被输出


为了获得预期的输出,同步块需要同时包含
run
println
语句的设置。另一个线程上的
run
println
语句的读取需要位于同一锁上的另一个同步块中。

如果只查看volatile变量的读取和写入,则它们必须按以下顺序出现:

1 - main: read run (run is true)
2 - Thread-0: write run (run is false)
3 - main: read run (run is false)
但是控制台输出是独立的操作,不需要在读取之后立即执行。println参数的计算和方法调用不是原子的。所以我们有一些更像:

1 - main: read run (run is true)
2 - main: println("Run: true")

3 - Thread-0: write run (run is false)
4 - Thread-0: println("Run: false")

5 - main: read run (run is false)
6 - main: println("Run: false")
这允许在第一次排序之后进行排序,如:

1 - main: read run (run is true)

3 - Thread-0: write run (run is false)
4 - Thread-0: println("Run: false")

2 - main: println("Run: true")

5 - main: read run (run is false)
6 - main: println("Run: false")
根据中的源代码,行:

System.out.println(Thread.currentThread().getName() + " run:" + run);
可以内联如下:

String x = Thread.currentThread().getName() + " run:" + run;
synchronized(System.out.lock) {
    System.out.print(x);
    System.out.println();
}
因此,
println
中存在同步,但不包括读取
run
。这意味着
run
的值可以在读取和输出之间更改,从而导致
run
的旧值被输出



为了获得预期的输出,同步块需要同时包含
run
println
语句的设置。另一个线程上的
run
println
语句的读取需要位于同一锁上的另一个同步块中。

请创建一个mvce。想要运行您发布的代码的人不必从不完整的代码片段中重建它。@NathanHughes:什么是mvce?在这个场景中还有另一个共享资源:
System.out
.mvce=最小值代码示例。@MikeSamuel:您介意解释一下吗?请制作一个mvce。想要运行您发布的代码的人不必从不完整的代码片段中重建它。@NathanHughes:什么是mvce?在这个场景中还有另一个共享资源:
System.out
.mvce=最小值代码示例。@MikeSamuel:您介意解释一下吗?嗯,我希望正确的行为类似于
main*run:true main*run:true main*run:true main*run:true main*run:true Thread-0将run设置为false main*run:true main*run:true main*run:true Thread-0 run:false main**run:false退出这有时会发生。那么,为什么会出现上述偏差呢?你能用预期的行为编辑帖子吗。很难在评论中读到谢谢是的,我理解你描述的流程。然而,让我困惑的是,即使
run
被指定为volatile,
main
线程在
Tread-0
中更新时(参见第一个片段),在第二个片段中更新时(根据System.out.println)也不会得到更新的值似乎完全不正常:
main
甚至在
Thread-0
中更新
run
之前就退出了。我在帖子的文本中添加了预期的行为。谢谢,我不太明白。您放入的时间戳似乎在重新排序
主线程中的
程序顺序
——这是否违反了根据Java内存模型规范定义为
volatile
运行
的合同,我希望正确的行为类似于
main*run:true main*run:true main*run:true main*run:true main*run:true Thread-0将run设置为false main*run:true main*run:true main*run:true Thread-0 run:false main**run:false退出这有时会发生。那么,为什么会出现上述偏差呢?你能用预期的行为编辑帖子吗。很难在评论中读到谢谢是的,我理解你描述的流程。然而,让我困惑的是,即使
run
被指定为volatile,
main
线程在
Tread-0
中更新时(参见第一个片段),在第二个片段中更新时(根据System.out.println)也不会得到更新的值似乎完全不正常:
main
甚至在
Thread-0
中更新
run
之前就退出了。我在帖子的文本中添加了预期的行为。谢谢,我不太明白。您输入的时间戳似乎在重新排序
主线程中的
程序顺序
-这是否违反了根据Java内存模型规范定义为
易失性
运行
的合同?Rafael,我昨天听了您的演讲,这就是为什么,激励我深入理解这个输出的行为。我还是很困惑。您说:“当A想要打印到控制台时,它需要为System.out重新请求监视器,这会导致刷新缓冲区,以便B中的后续消息打印更新的消息。”但是,此顺序与此前提相矛盾:
Thread-0 run:false
main*run:true
main**run:false
// run = false; //becomes ========
synchronized(someLock) {
    run = flase;
}
// =======================


//System.out.println(run); //becomes =========   
synchronized(someLock) {
    boolean tmpBoolean = run;
}
System.out.println(tmpBoolean);
//=================
System.out.println(Thread.currentThread().getName() + "* run: " + run);
String text = Thread.currentThread().getName() + "* run: " + run;
System.out.println(text);
/*A*/ String text = Thread.currentThread().getName() + "* run: " + run;
/*B*/ System.out.println(Thread.currentThread().getName() + " setting run to false");
/*B*/ run = false;
/*B*/ System.out.println(Thread.currentThread().getName() + " run:" + run);
/*A*/ System.out.println(text);
/*A*/ if(run == false) {
/*A*/ System.out.println(Thread.currentThread().getName() + "** run: " + run + "\nExiting...");
/*A*/ System.exit(0);
/*A*/ }
1 - main: read run (run is true)
2 - Thread-0: write run (run is false)
3 - main: read run (run is false)
1 - main: read run (run is true)
2 - main: println("Run: true")

3 - Thread-0: write run (run is false)
4 - Thread-0: println("Run: false")

5 - main: read run (run is false)
6 - main: println("Run: false")
1 - main: read run (run is true)

3 - Thread-0: write run (run is false)
4 - Thread-0: println("Run: false")

2 - main: println("Run: true")

5 - main: read run (run is false)
6 - main: println("Run: false")
System.out.println(Thread.currentThread().getName() + " run:" + run);
String x = Thread.currentThread().getName() + " run:" + run;
synchronized(System.out.lock) {
    System.out.print(x);
    System.out.println();
}