考虑以下方法:
public void upsert(int customerId, int somethingElse) {
// some code which is prone to race conditions
}
我想保护此方法不受竞争条件的影响,但只有当两个具有相同customerId
的线程同时调用它时才会发生这种情况。如果我制作整个方法synchronized
,它将降低效率并且不是真正需要的。我真正想要的是在customerId
周围进行同步。这有可能以某种方式与Java?是否有任何内置工具,或者我需要Map
Integers
作为锁使用?
如果您认为我在这里做错了,请随时提出建议:)
谢谢!
答案 0 :(得分:11)
您正在寻找的概念称为分段锁定或条带锁定。为每个客户设置一个单独的锁是非常浪费的(锁是非常重量级的)。相反,您希望将客户ID空间分区分成合理数量的分区,以匹配所需的并行度。通常8-16就足够了,但这取决于该方法的工作量。
这概述了一种简单的方法:
private final Object[] locks = new Object[8];
synchronized (locks[customerId % locks.length]) {
...implementation...
}
答案 1 :(得分:0)
private static final Set<Integer> lockedIds = new HashSet<>();
private void lock(Integer id) throws InterruptedException {
synchronized (lockedIds) {
while (!lockedIds.add(id)) {
lockedIds.wait();
}
}
}
private void unlock(Integer id) {
synchronized (lockedIds) {
lockedIds.remove(id);
lockedIds.notifyAll();
}
}
public void upsert(int customerId) throws InterruptedException {
try {
lock(customerId);
//Put your code here.
//For different ids it is executed in parallel.
//For equal ids it is executed synchronously.
} finally {
unlock(customerId);
}
}