【发布时间】:2013-05-30 15:01:59
【问题描述】:
我想根据一些 id 同步方法调用,例如给定对象实例的并发装饰器。
例如:
所有使用参数“id1”调用该方法的线程都应该彼此串行执行。
其余所有调用具有不同参数(例如“id2”)的方法的所有线程都应与使用参数“id1”调用该方法的线程并行执行,但又彼此串行执行。
所以在我看来,这可以通过为每个此类方法参数设置一个锁 (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantLock.html) 实例来实现。 每次使用参数调用方法时,都会查找与特定参数值(例如“id1”)对应的锁实例,并且当前线程会尝试获取锁。
用代码说话:
public class ConcurrentPolicyWrapperImpl implements Foo {
private Foo delegate;
/**
* Holds the monitor objects used for synchronization.
*/
private Map<String, Lock> concurrentPolicyMap = Collections.synchronizedMap(new HashMap<String, Lock>());
/**
* Here we decorate the call to the wrapped instance with a synchronization policy.
*/
@Override
public Object callFooDelegateMethod (String id) {
Lock lock = getLock(id);
lock.lock();
try {
return delegate.delegateMethod(id);
} finally {
lock.unlock();
}
}
protected Lock getLock(String id) {
Lock lock = concurrentPolicyMap.get(id);
if (lock == null) {
lock = createLock();
concurrentPolicyMap.put(id, lock);
}
return lock;
}
}
protected Lock createLock() {
return new ReentrantLock();
}
这似乎可行——我用 jmeter 等做了一些性能测试。 尽管如此,我们都知道 Java 中的并发是一件棘手的事情,所以我决定在这里征求您的意见。
我无法停止思考是否有更好的方法来实现这一点。例如,通过使用 BlockingQueue 实现之一。你怎么看?
我也无法确定获取锁是否存在潜在的同步问题,即protected Lock getLock(String id) 方法。我正在使用同步集合,但这是否足够? IE。它不应该是类似于以下内容,而不是我目前拥有的内容:
protected Lock getLock(String id) {
synchronized(concurrentPolicyMap) {
Lock lock = concurrentPolicyMap.get(id);
if (lock == null) {
lock = createLock();
concurrentPolicyMap.put(id, lock);
}
return lock;
}
}
你们觉得呢?
【问题讨论】:
标签: java concurrency locking