不同方法的同步 类

Synchronization of methods of differents classes

我有两个 类 每个都有一种方法。

class A {
    private void insert(String usedId){
        // ...
    }
}

class B {
    private void refresh(String userId){
        // ...
    }
}

每个方法都是从不同的 Thread 调用的。它们是从不同的 Thread 调用的,用于不同的 userId

我需要在调用第二个方法时锁定第一个方法,反之亦然 userId

持有List个id并加锁是不是最好的选择?

我们介绍一个LockDispenser。您将此对象传递给您想要 thread safe 的所有 AB。它将提供 Lock 个带有 createLock(String forId) 的对象,这些对象需要在使用后通过调用 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

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 块中。

并像这样创建它们:

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);
}

fooAfooB 彼此是线程安全的,barAbarB.

也是如此