不同方法的同步 类
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 的所有 A
和 B
。它将提供 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);
}
fooA
和 fooB
彼此是线程安全的,barA
和 barB
.
也是如此
我有两个 类 每个都有一种方法。
class A {
private void insert(String usedId){
// ...
}
}
class B {
private void refresh(String userId){
// ...
}
}
每个方法都是从不同的 Thread
调用的。它们是从不同的 Thread
调用的,用于不同的 userId
。
我需要在调用第二个方法时锁定第一个方法,反之亦然 userId
。
持有List
个id并加锁是不是最好的选择?
我们介绍一个LockDispenser
。您将此对象传递给您想要 thread safe 的所有 A
和 B
。它将提供 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);
}
fooA
和 fooB
彼此是线程安全的,barA
和 barB
.