我有两个类,每个类都有一种方法。
class A {
private void insert(String usedId){
// ...
}
}
class B {
private void refresh(String userId){
// ...
}
}
每个方法都是从不同的线程
调用的。它们是从不同的 Thread
为不同的 userId
调用的。
当调用第二个方法时,我需要锁定第一个方法,对于相同的userId
,反之亦然。
保存 ID 的 List
并设置锁定是最佳选择吗?
最佳答案
我们引入了一个LockDispenser
。您将此对象传递给您想要拥有的所有 A
和 B
thread safe 。它将通过 createLock(String forId)
提供 Lock
对象,使用后需要通过调用 releaseLock(String forId)
释放该对象。
public class LockDispenser {
private final Map<String, Lock> dispenser = new LinkedHashMap<>();
public Object createLock(String forId) {
synchronized (dispenser) {
if (!dispenser.containsKey(forId)) {
dispenser.put(forId, new Lock());
}
Lock lock = dispenser.get(forId);
lock.referenceCounter++;
return lock;
}
}
public void releaseLock(String forId) {
synchronized (dispenser) {
Lock lock = dispenser.get(forId);
lock.referenceCounter--;
if (lock.referenceCounter == 0) {
dispenser.remove(forId);
}
}
}
public static class Lock {
private int referenceCounter = 0;
}
}
<小时/>
现在,实际的线程安全来自于在 synchronized
中使用 Lock
block 。
public class A {
private LockDispenser dispenser;
public A(LockDispenser dispenser) {
this.dispenser = dispenser;
}
private void insert(String userId) {
synchronized (dispenser.createLock(userId)) {
// code
}
dispenser.releaseLock(userId); // consider putting this in a finally block
}
}
<小时/>
public class B {
private LockDispenser dispenser;
public B(LockDispenser dispenser) {
this.dispenser = dispenser;
}
private void refresh(String userId) {
synchronized (dispenser.createLock(userId)) {
// code
}
dispenser.releaseLock(userId); // consider putting this in a finally block
}
}
即使抛出异常,也要确保调用releaseLock(String forId)
。您可以通过将其放入 finally
来做到这一点 block 。
并像这样创建它们:
public static void main(String... args) {
LockDispenser fooLock = new LockDispenser();
A fooA = new A(fooLock);
B fooB = new B(fooLock);
LockDispenser barLock = new LockDispenser();
A barA = new A(barLock);
B barB = new B(barLock);
}
fooA
和 fooB
彼此是线程安全的,barA
和 barB
也是如此。
关于java - 不同类方法的同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49758748/