gpt4 book ai didi

java - 在没有读锁的情况下使用 writeLock 是否安全?

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

假设这是一个“单例”实现:我能保证这只会调用 productCatalogLoader.load() 一次,并且不会发生空指针吗?有什么办法可以使这更简单吗?

private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private ProductCatalog productCatalog;

public ProductCatalog get() {
if (this.productCatalog == null) {
reload();
}
return this.productCatalog;
}

public void reload() {

lock.writeLock().lock();
try {
if (this.productCatalog != null) return;
this.productCatalog = productCatalogLoader.load();
} finally {
lock.writeLock().unlock();
}
}

编辑:这是一次比较成功的尝试,将复杂得多的代码简化为一个简单的问题示例。有几个人发现我的单例太复杂了;)(实际上还有一个 quartz 计时器调用重新加载,但“重新加载”实现与 IRL 有点不同)。无论如何,我得到了我需要的答案,破坏了双重检查锁定。

最佳答案

简化它的最好方法,IMO,是使用“普通”锁,除非你真的有很好的证据表明它会导致瓶颈:

private final Object lock = new Object();
private ProductCatalog productCatalog;

public ProductCatalog get() {
synchronized (lock) {
if (this.productCatalog == null) {
this.productCatalog = productCatalogLoader.load();
}
return this.productCatalog;
}
}

在绝大多数情况下,这已经足够好了,您无需担心内存模型技术问题。

编辑:至于在不获取读锁的情况下读取写锁中更改的数据是否安全 - 我怀疑不安全,但我不想肯定地说。使用 volatile 变量使用普通(并且在 Java 1.5+ 上是安全的,如果你小心的话)双重检查锁定的方法有什么好处吗?

private final Object lock = new Object();
private volatile ProductCatalog productCatalog;

public ProductCatalog get() {
if (this.productCatalog == null) {
synchronized (lock) {
if (this.productCatalog == null) {
this.productCatalog = productCatalogLoader.load();
}
}
}
return this.productCatalog;
}

我相信这是 Effective Java 第 2 版中推荐的惰性初始化技术,适用于静态初始化器不够用的情况。请注意,productCatalog 必须是易变的才能使其正常工作 - 我认为这有效您没有取消代码中的读取锁定而错过了什么。

关于java - 在没有读锁的情况下使用 writeLock 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/775936/

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