gpt4 book ai didi

java - java线程缓存什么时候刷新?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:18:00 26 4
gpt4 key购买 nike

线程1:正在执行这个循环

while(running) {
// Do Task()
}
println("Done");

线程 2 设置为 running false如果 running 是一个可变变量,thread1 会退出循环并打印“Done”。

我的问题是,如果 running 不是 volatile,Thread1 什么时候从主存中读取 running 变量?

注意:好吧,我知道关于同步和 volatile 变量的关系发生在发生之前,但线程 1 确实停止,即使运行不是 volatile 或同步的。所以我的问题是线程 1 什么时候决定从主内存中读取,因为没有同步或没有 volatile

最佳答案

这在 Threads and Locks 部分下的 JLS 中进行了描述.

线程何时需要从主内存读取是根据同步顺序定义的,发生在顺序之前。基本上它说,为了让读取产生最后写入的值,写入需要发生在读取之前。

happens-before 关系粗略地说是根据锁定/解锁操作定义的,并且(除了少数异常(exception))归结为同步方法和 block 的使用。除非您正在处理 volatile 变量,否则底线通常是您需要同步对共享数据的所有访问,最好是通过 AtomicBooleanBlockingQueue 或其他一些 java.lang. util.concurrent 类。

17.4.4 Synchronization Order

Every execution has a synchronization order. A synchronization order is a total order over all of the synchronization actions of an execution. For each thread t, the synchronization order of the synchronization actions (§17.4.2) in t is consistent with the program order (§17.4.3) of t.

Synchronization actions induce the synchronized-with relation on actions, defined as follows:

  • An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where subsequent is defined according to the synchronization order).
  • A write to a volatile variable (§8.3.1.4) v synchronizes-with all subsequent reads of v by any thread (where subsequent is defined according to the synchronization order).
  • An action that starts a thread synchronizes-with the first action in the thread it starts.
  • The write of the default value (zero, false or null) to each variable synchronizes-with the first action in every thread. Although it may seem a little strange to write a default value to a variable before the object containing the variable is allocated, conceptually every object is created at the start of the program with its default initialized values.
  • The final action in a thread T1 synchronizes-with any action in another thread T2 that detects that T1 has terminated. T2 may accomplish this by calling T1.isAlive() or T1.join().
  • If thread T1 interrupts thread T2, the interrupt by T1 synchronizes-with any point where any other thread (including T2) determines that T2 has been interrupted (by having an InterruptedException thrown or by invoking Thread.interrupted or Thread.isInterrupted).

The source of a synchronizes-with edge is called a release, and the destination is called an acquire.

17.4.5 Happens-before Order

Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.

If we have two actions x and y, we write hb(x, y) to indicate that x happens-before y.

  • If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
  • There is a happens-before edge from the end of a constructor of an object to the start of a finalizer (§12.6) for that object.
  • If an action x synchronizes-with a following action y, then we also have hb(x, y).
  • If hb(x, y) and hb(y, z), then hb(x, z).

It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal.


更新:如果不存在先行发生关系,永远不需要线程“刷新其缓存”This question它被接受的答案提供了一个具体的例子。

这是已接受答案的略微修改版本:

public class Test {

static boolean keepRunning = true;

public static void main(String[] args) throws InterruptedException {

(new Thread() {
public void run() {
while (keepRunning) {
}
}
}).start();

System.out.println(keepRunning);
Thread.sleep(1000);
keepRunning = false;
System.out.println(keepRunning);

// main thread ends here, but the while-thread keeps running.
// (but not if you change the keepRunning to volatile).
}
}

关于java - java线程缓存什么时候刷新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5022100/

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