【发布时间】:2021-09-26 08:41:00
【问题描述】:
我实现了一个简单的锁定解决方案,它为一个值而不是对象创建一个锁,并且想了解专家对可能的性能或安全缺陷的看法。 这个想法是使用它来更新帐户余额,获取唯一帐号的锁定。
这是一个实现:
import java.util.*;
public class Mutex<T> {
private final Set<T> set = new HashSet();
public synchronized Lock acquireLock(
T value
) throws InterruptedException {
while(!set.add(value)) {
this.wait();
}
return new Lock(value);
}
public class Lock {
private final T value;
public Lock(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void release() {
synchronized(Mutex.this) {
set.remove(value);
Mutex.this.notifyAll();
}
}
}
}
以下是检查可操作性的示例用法:
public class Test {
private Mutex mutex = new Mutex();
public static void main(String[] args) {
Test test = new Test();
Thread t1 = new Thread(() -> {
try {
test.test("SameValue");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
t1.setName("Thread 1");
Thread t2 = new Thread(() -> {
try {
test.test("SameValue");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
t2.setName("Thread 2");
t1.start();
t2.start();
}
public void test(String value)
throws
InterruptedException {
Lock lock = mutex.acquireLock(value);
try {
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName());
} finally {
lock.release();
}
}
}
【问题讨论】:
-
也许我遗漏了一些东西,但老实说,我不明白为什么需要这段代码。一个简单的
synchronized (value) { ... }不会达到完全相同的目的,消除对整个 Mutex 类的需要吗?当然,您可以稍微加强一下,以便所有等效字符串都引用同一个锁对象,但我认为您正在使用 Mutex 类重新发明轮子。 -
@CharlieArmstrong 同步块使用对象,我只有 Account IBAN 值(字符串)。我知道 String.intern() 方法,但它有 GC 问题。关于“所有等价的字符串都引用同一个锁对象”——我们有数百万个账户记录,所以将它们的 IBAN 存储在 HashMap 中并不是一个好的解决方案
-
嗯,好的,我明白你现在在说什么。我不知道有什么好的解决方案。您的解决方案可能是最简单的方法,只是对我来说,这感觉就像必须有一种更内置的方法来做到这一点。如果没有一个 Java 库有这方面的功能,我会感到惊讶。
-
@CharlieArmstrong 同意,我也一样,这就是为什么我的问题在这里 :) 让我们看看
-
在
if(condition) …中包装while(condition) …循环是没有意义的,循环确实已经进行了预测试。当true时,您只是执行了两次相同的测试。除此之外,既然您将list更改为Set,您也不应该将变量命名为list,此外,add合约已经足以测试存在性。换句话说,你可以简单地使用while(!set.add(value)) { this.wait(); } return new Lock(value);就可以了。
标签: java concurrency locking