【发布时间】:2020-05-15 21:45:41
【问题描述】:
我正在尝试通过优化同步块来修复服务。我得到了两个不同的值,我的双重检查单例与一个易失的字符串似乎不起作用?
get 和 Increment 字符串在 DB 上设置行锁并递增字符串,因此仅在 DB 级别处理唯一更新。所以在第一种情况下,没有问题。
问题在于else blozk。当相关 ID 不为空时,如果这是第一次调用,我们会尝试获取已映射的值。然后我们首先映射该值,然后返回它。此映射必须同步,以便两个不同的线程不会更新下一个 val agter,它们都发现它为空。
这个类也是一个单例服务。
public class RangeQueryService{
private volatile String nextValue=null;
public String getNextIncrement(String name, String correlationId) throws SomeCheckedException {
try {
if (correlationId == null) {
nextValue = rangeFetch.getAndIncrementAsString(name);
} else { //Enter Sync branch
// mapper Will Return null if no value is mapped.
nextValue = mapper.mapToB(SOME_CONST, correlationId);
// Avoid syncronization overhead if value is already fetched. Only enter if nextVal is null.
if (nextValue == null) {
synchronized (this) {
Doubly Check lock pattern, as two threads can find null simultaneously, and wait on the critical section.
if(nextValue==null){
nextValue = rangeFetch.getAndIncrementAsString(name);
idMapper.mapToB(SOME_CONST, correlationId, nextValue, DURATION);
}
}
}
}
return nextValue;
} catch (Exception e) {
throw new SomeCheckedException("Error!" + e.getMessage());
}
}
它返回 19 和 20。它应该只返回 19。
输出:
headerAfterProcessOne: 0000000019, headerAfterProcessTwo: 0000000020
【问题讨论】:
-
你能说明你是如何使用这个方法的吗?还有,为什么不能同步整个方法?
-
如果相关 id 为空,同步整个方法会导致同步,但在这种情况下不需要同步。
-
您是否尝试将额外的
nextValue = mapper.mapToB(SOME_CONST, correlationId);作为同步块的第一行? -
之前的代码是如何被破解的,需要优化锁定?您如何确定这是问题所在?
标签: java multithreading thread-safety singleton locking