Java 锁定条件和特定值
我已经开始阅读实践中的Java并发,但在继续之前,我有一个需要解决的想法 以这段代码为例。 我用番石榴()来检索Java 锁定条件和特定值,java,multithreading,Java,Multithreading,我已经开始阅读实践中的Java并发,但在继续之前,我有一个需要解决的想法 以这段代码为例。 我用番石榴()来检索锁(s)。 顺便说一句,我知道,正如Guava文档所述,这类似于使用ConcurrentHashMap public Object getValue(final String input) { final Lock inputLock = STRIPED.get(input); try { inputLock.lock(); Object valu
锁
(s)。
顺便说一句,我知道,正如Guava文档所述,这类似于使用ConcurrentHashMap
public Object getValue(final String input) {
final Lock inputLock = STRIPED.get(input);
try {
inputLock.lock();
Object value = VALUES.get(input);
if (value == null) {
value = buildValue(input);
VALUES.put(input, value);
}
return value;
} finally {
inputLock.unlock();
}
}
现在,它通过基于输入值锁定来工作。但是,如果在大多数情况下使用相同的值调用
getValue(…)
方法,则我将不进行任何同步,因为同步仅用于第一次也是唯一一次写入
如何优化这段代码(如果可能)?
如果不想锁定这些现有值,只需移动
值。从锁定部分中取出。然后在锁定时再次检查值
public Object getValue(final String input) {
Object value = VALUES.get(input);
if (value == null) {
Lock lock = STRIPED.get(input);
try {
lock.lock();
value = VALUES.get(input);
if (value == null) {
value = buildValue(input);
VALUES.put(input, value);
}
} finally {
lock.unlock();
}
}
return value;
}
如果您想了解锁定,那么您就走上了正确的道路
如果您想在关键应用程序中实际使用它,最好使用此模式的标准实现,例如Guava的LoadingCache,它重用ConcurrentHashMap的双重锁定逻辑,但也允许以线程安全的方式计算值
看
即使您不需要逐出逻辑,对于线程安全的惰性计算缓存来说,这仍然是一个很好的解决方案。您尝试实现的功能可以使用Java 8中的ConcurrentHashMap完成
public Object getValue(final String input) {
return chm.computeIfAbsent(input, ip -> buildValue(ip));
}
我不是番石榴专家,但通常您会通过某种形式的双重检查锁定(只要值标记为volatile)来实现这一点。您首先调用值。get()
,然后如果返回null,则获取一个锁,然后从该锁中再次进行相同的调用。如果该调用也返回null,您可以继续,构建值,然后在再次释放锁之前将其插入到映射中。@MichaelBerry Oh Guava在这里并不重要。谢谢你的解释。你为什么用条纹呢?您可以使用ConcurrentHashMap computeIfAbsent实现同样的功能method@NeeravVadodaria这只是为了学习。正如我所说的,我知道我可以使用ConcurrentHashMap,但我想知道可能的优化是什么be@MichaelBerry寻找戈茨书中的“双重检查锁定”,他说这是一种需要避免的反模式。因此,我认为如果不完全切换策略,这段代码是无法优化的。这看起来有点“奇怪”,但如果这是唯一的方法,那么就没关系了。@LppEdd我不知道是否还有其他方法。关于这个方法的更多信息,您可以签出。我通常会选择单例的惰性类初始化方法。它没有那么冗长和冗余。如果它带有多线程,总会有一些冗长的东西。我最不喜欢的是双映射#get调用。这可能会成为一项繁重的操作,尤其对于使用旧版本Java 8的人来说,这可能非常有用。谢谢,嗨!值得一提的是,它仅适用于Java8+用户。