我们正在使用面向服务的体系结构,并且有一个多线程应用程序来处理请求。这些请求需要从所有线程共享的大对象中读取某些值,并且必须通过从数据库中读取它来定期刷新(例如,频率为每天一次)。
定期刷新此大对象可能需要几分钟时间,我们的服务仍必须继续使用对象的较旧缓存值来处理请求。换句话说,在我们拥有对象的最新值之前,我们不希望阻止请求。
我们正在考虑做以下事情:
守护程序线程可以读取数据库并将对象重新构建为新变量。稍后,可以将新对象的引用复制到包含先前缓存的对象的变量上。但是,我们不确定引用的复制是否可以说是合理的线程安全操作(我们不需要它完全是线程安全的)。
换句话说,如果守护程序线程按如下方式更新共享变量A(不锁定它):
A = B;
那时,如果另一个线程试图读取A,它是否总是只读取A的新值或旧值(两者都是我们可接受的场景),还是可能最终读取一些垃圾值?如果我们明确需要锁定A,那么我们的请求的延迟可能会上升。
欢迎任何其他建议。
谢谢!
答案 0 :(得分:1)
在Java中,赋值是原子的。
问题是线程可以缓存非volatile
变量,因此不要查看更新。这是可见性的问题。在最坏的情况下,另一个线程可能从不看到更新的值。
您应该将变量标记为volatile
,以确保在重新分配变量时,所有线程都可以看到变量。这确实有一些成本,但这是必需的。
Here解释了在内存访问方面使用volatile
的含义。