如何重构基于字符串的同步块

How to refactor a synchronization block based on string

我正在重构一个遗留项目,我发现了一个使用 String 进行同步的代码(实际上它是一个缓存实现)。

public void method (String key, ...) {

 synchronized(key) {
   ....
  }
}

只有一个块在 String 对象上同步 key

我想知道 fixing/Refactoring 代码的最佳方式是什么?

有什么想法吗?

一种方法是采用以下模式:

private final ConcurrentHashMap<String, Object> lockMap = new ConcurrentHashMap<>();
public void method(String key, ...) {
    synchronized(getLock(key)) {
        ....
    }
}
protected Object getLock(String key) {
    Object newLock = new Object(), lock = lockMap.putIfAbsent(key, newLock);
    return lock == null? newLock: lock;
}

请注意,这是一个经过验证的模式,因为 Java 7 引入的并行 class 加载程序也使用它。

使用Java 8,可以简化代码:

protected Object getLock(String key) {
    return lockMap.computeIfAbsent(key, x->new Object());
}