gpt4 book ai didi

Java Concurrency volatile 读同步写

转载 作者:行者123 更新时间:2023-11-30 10:13:39 26 4
gpt4 key购买 nike

我需要创建一个具有线程间共享对象的类(让我们调用 SharedObject)。 SharedObject 的特殊之处在于它持有一个在多线程环境下将返回的字符串,有时整个 SharedObject 将通过更改字段引用到新创建的对象来写入。

我不想在同一个监视器上同步读取和写入两者,因为写入场景很少发生,而读取场景却很常见。因此我做了以下事情:

public class ObjectHolder {
private volatile SharedObject sharedObject;

public String getSharedObjectString() {
if (!isObjectStillValid()) {
obtainNewSharedObject()
}
return sharedObject.getCommonString()
}

public synchronized void obtainNewSharedObject() {
/* This is in case multiple threads wait on this lock,
after first one obtains new object the others can just
use it and should not obtain a new one */
if(!isObjectStillValid()) {
sharedObject = new SharedObject(/*some parameters from somewhere*/)
}
}
}

根据我从文档和 stackoverflow 上读到的内容,synchronized 关键字将确保只有一个线程可以访问同一对象实例上的同步块(synchronized block)(因此写入竞争/多次不必要的写入是非-issue) 而字段引用上的 volatile 关键字将确保将引用值直接写入主程序内存(不在本地缓存)。

还有我遗漏的任何其他陷阱吗?

我想确保在写入 sharedObject 时在同步块(synchronized block)内,sharedObject 的新值最迟在锁定 时出现在任何其他线程中>obtainNewSharedObject() 已发布。如果不能保证这一点,我可能会遇到不必要的写入和替换正确值的情况,这对这种情况来说是个大问题。

我知道为了绝对安全,我可以自己制作 getSharedObjectString() synchronized 但是如前所述,如果不需要,我不想阻止读取。这样读取是非阻塞的,当发生写入场景时它是阻塞的。我可能应该提到方法 isObjectStillValid() 是线程独立的(完全基于 SharedObject 和系统时钟)因此有效的无线程检查用于写场景。

编辑:请注意我在 stackoverflow 上找不到类似的主题,但它可能存在。抱歉,如果是这样的话。

Edit2:感谢您的所有评论。编辑因为显然我还不能投票(我可以,但它没有显示)。虽然只要 isObjectStillValid 是线程安全的,我的解决方案就可以正常工作,但它可能会因多次访问 volatile 字段而导致性能下降。我最有可能使用升级双重检查锁定解决方案来改进它。我还将深入分析这里提到的所有其他可能性。

最佳答案

你为什么不使用AtomicReference .它使用乐观锁定,这意味着不涉及实际的线程锁定。在内部它使用 Compare and Swap .如果你看一下它在实现中使用 volatile 的实现,我相信 Doug Lea 会正确地实现它:)

除此之外,还有很多方法可以在很多读者和一些作者之间进行同步 - ReadWriteLock

关于Java Concurrency volatile 读同步写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51248760/

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