gpt4 book ai didi

java - 如何使用synchronized关键字避免过时数据?

转载 作者:行者123 更新时间:2023-12-01 19:34:54 25 4
gpt4 key购买 nike

在《Java并发实践》一书中,3.1.1状态数据一节下,有一段代码

@NotThreadSafe
public class MutableInteger {
private int value;
public int get() { return value; }
public void set(int value) { this.value = value; }
}

这不是线程安全的,因为:

if one thread calls set, other threads calling get may or may not see that update.

而在 set 和 get 方法上使用同步关键字使其“正确”。怎么办?

@ThreadSafe
public class SynchronizedInteger {
@GuardedBy("this") private int value;
public synchronized int get() { return value; }
public synchronized void set(int value) { this.value = value; }
}

这里,如果 value 为 0,并且线程 A 调用了 set(2),而线程 B 调用了 get(),B 可能会获取值 0,然后 A 会将其设置为 2...前面的代码已经这样做了。那么同步代码给我们带来了什么好处..

也许我遗漏了一些东西,但请指导。谢谢

最佳答案

您以这种方式解决的问题不是线程 B 在 A 执行 get 之后立即执行集合,该线程仍将返回“旧”(好吧,当时技术上是正确的,但是很快就会错)值。

同步修复的问题是,即使线程 B 在线程 A 读取之前写入,A 也可能由于缓存而读取旧值(很可能是 CPU 缓存,但是这取决于 JVM 实现)。对非 volatile 变量的非同步读取可以使用缓存值。换句话说:synchronized 创建了一个读屏障,这意味着“你必须重新读取这个值,即使你的 CPU 缓存中已经有它”。

请注意,对于这种特定情况,只需将 volatile 添加到 value 就会产生相同的效果,但对于更复杂的访问模式synchronized (或者它在较新的 API 中的等效项 Lock ) 是必要的。

关于java - 如何使用synchronized关键字避免过时数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58198773/

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