gpt4 book ai didi

Java happens-before 关系

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:49:21 26 4
gpt4 key购买 nike

虽然在 SO 和其他地方有很多关于 happens-before 关系的帖子,但我很难找到我的问题的明确答案。

考虑两个 Java 线程:

最初,flag == falsedata == 0

T1

data = 42;
synchronized(m) {
flag = true;
}

T2

boolean f;
synchronized(m) {
f = flag;
}
if (f) {
int x = data;
}

根据上面的代码,我相信f可以赋值为truefalse,没有保证。这是正确的吗?

现在,如果将两个 synchronized 语句更改为 synchronized(flag),我认为指令 flag = true 将始终发生在指令 f = flag,因此 f 将始终被赋予值 true。这是正确的吗?

最佳答案

不,synchronized 不保证哪个 Thread 先到达那里。 In only 保证多个 Thread 不能同时访问同步块(synchronized block)。

synchronized block 想象成一个门上有锁的房间。我们不知道谁会先到门口,但一旦他们到达,他们就会进去并锁上门。

其他人必须等到房间里的人准备离开并打开门锁。一旦发生这种情况,每个人都争相再次进门。

这完全取决于您关闭 Thread 的顺序。但即便如此,也无法保证,因为 JVM 可能会随机暂停 ThreadThreadyield。在类比中 - 领先到门口的人可能会被香蕉皮绊倒。不可能,但总是有可能。

如果你想得到保证,那么你需要wait/notify - 这样读取线程会检查flag,如果它是false,将自身挂起在一个循环中。

写入线程然后设置标志并通知唤醒读取线程的锁监视器。

这是一个使用 Java 5 中的 LockCondition api 的示例。我并不是说您必须在偏好 synchronizedwait/notify - 这只是我改编的一个例子。

Reader 获取,然后循环检查ready 标志。如果标志为 false,它会在条件下await。这会自动释放 lock 并暂停 Thread

Writer 同时获取lock 并设置dataready 标志。然后调用 signalAll 并释放 lock

这会唤醒 Reader,然后读取 readytrue 并继续执行 print 语句。

输出将始终为 42(永远不会是 -1)。

public class App {

static volatile boolean ready = false;
static volatile int data = -1;

private static class Reader implements Runnable {

private final Lock lock;
private final Condition condition;

public Reader(Lock lock, Condition condition) {
this.lock = lock;
this.condition = condition;
}

@Override
public void run() {
lock.lock();
try {
while (!ready) {
try {
condition.await();
} catch (InterruptedException ex) {
//oh well
}
}
System.out.println(data);
} finally {
lock.unlock();
}
}
}

private static class Writer implements Runnable {

private final Lock lock;
private final Condition condition;

public Writer(Lock lock, Condition condition) {
this.lock = lock;
this.condition = condition;
}

@Override
public void run() {
lock.lock();
try {
data = 42;
ready = true;
condition.signalAll();
} finally {
lock.unlock();
}
}
}

public static void main(String[] args) throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(2);
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
executorService.execute(new Reader(lock, condition));
executorService.execute(new Writer(lock, condition));
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
}
}

关于Java happens-before 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16239416/

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