gpt4 book ai didi

java - Java volatile字段跨线程读写协调理解

转载 作者:行者123 更新时间:2023-11-29 08:42:03 24 4
gpt4 key购买 nike

我有以下代码:

 private volatile boolean run = true;

private Object lock =new Object();

…………

Thread newThread = new Thread(new Runnable() {

@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {

e.printStackTrace();
}
synchronized (lock) {
System.out.println(Thread.currentThread().getName()
+ " run:" + run);

System.out.println(Thread.currentThread().getName()
+ " setting run to false");

run = false;

System.out.println(Thread.currentThread().getName()
+ " run:" + run);
}
}});

newThread.start();

while(true) {//no synchronization, so no coordination guarantee
System.out.println(Thread.currentThread().getName() + "* run: "+run);

if(run == false) {
System.out.println(Thread.currentThread().getName() + "** run: "+run+"\nExiting...");
System.exit(0);
}
}




which generates the following output:



main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
Thread-0 setting run to false
Thread-0 run:false
main* run: true <- what causes this???
main** run: false
Exiting...

我试图理解为什么在主线程中发生 ma​​in* run: true 的异常,考虑到 run 是一个易变的字段并且根据 Java 内存模型规范中,Thread-0 中的 volatile 写入应该立即被 main 线程可见。我知道 Thread-0 中的同步在这里是无关紧要的,但我对 volatile 的这种行为感到困惑。我在这里错过了什么?

另一个更奇怪的运行产生了这个:

main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main** run: false
Exiting...
Thread-0 run:false

或者这种行为是可以预料的,如果是,为什么?谢谢。

编辑:正如评论中所问,我正在用我有时但并非总是看到的预期输出更新帖子:

main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
main* run: true
Thread-0 setting run to false
main* run: true
main* run: true
main* run: true
Thread-0 run:false
main** run: false
Exiting...

换句话说,我不想看到:

main* run: true 

出现在

之后
Thread-0 run:false

main** run: false
Exiting...

出现在

之前
Thread-0 run:false

最佳答案

我没有看到问题。这里的锁是没用的。 volatile 也意味着变量在自身内部是同步的。这里发生了什么。每当有多个线程时,每个线程都会自行运行而不关心其他线程。所以在这种情况下,我们有两个线程:main 和 thread-0。 Main 自行运行并到达打印变量 run 的位置,因此它会打印它。另一个线程 hibernate 了一点(这应该无关紧要,也不应该是让其他线程先工作的方式),然后将变量 run 更改为 false。主线程读取新值并存在

按照时间顺序你就明白了

Thread newThread = new Thread(new Runnable() {

@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {

e.printStackTrace();
}
synchronized (lock) {
System.out.println(Thread.currentThread().getName()
+ " run:" + run);

System.out.println(Thread.currentThread().getName()
+ " setting run to false");

run = false; //<---- time_4

System.out.println(Thread.currentThread().getName()
+ " run:" + run); //<---- time_5
}
}});

newThread.start();

while(true) { //<---- time_2
System.out.println(Thread.currentThread().getName() + "* run: "+run); //<--- time_3 getting the value of run variable. //<---- time_6 printing

if(run == false) { //<---- time_1 (run == true) // <---- 2nd iteration time_7 (run == false)
System.out.println(Thread.currentThread().getName() + "** run: "+run+"\nExiting..."); //<---- time_8
System.exit(0);
}
}

无论如何,这里是如何修复你的代码以获得预期的输出(注意:volatile 在这里没有做任何事情):

synchronized (lock) {
if(run == false) {
System.out.println(Thread.currentThread().getName() + "** run: "+run+"\nExiting...");
System.exit(0);
}
}

这就是 volatile 对变量 run 的基本作用:

// run = false; //becomes ========
synchronized(someLock) {
run = flase;
}
// =======================


//System.out.println(run); //becomes =========
synchronized(someLock) {
boolean tmpBoolean = run;
}
System.out.println(tmpBoolean);
//=================

关于java - Java volatile字段跨线程读写协调理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39312933/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com