我们正在编写一个并发的multimap,以便在多线程应用程序中存储相同密钥的多个值。我们已经扩展了番石榴ForwardingMultimap来做同样的事情。Put和remove方法获取密钥上的写锁,并在最后释放它。类似地,获取密钥上的读锁并在结束时释放它。我已经通过在本地系统中使用多个线程来测试这一点,而且它工作得很好。
现在问题在于clear方法,如果一个线程正在执行put/remove,而另一个线程执行清除,那么就会出现不一致性。为了解决这个问题,我们用清晰的方法决定在公钥上添加一个写锁,并在最后发布它。类似地,put和remove方法也得到了改进,在公钥上有一个读锁,并在最后释放它。就像下面这样。
IResourceLockManager mLocks = new ResourceLockManager();
private final String mPublicKey = "$public";
private final int mLockTimeOut = 0;放置/删除操作
public boolean put(Object aKey, Object aValue) {
mLocks.acquireReadLock(mPublicKey, mLockTimeOut);
mLocks.acquireWriteLock(aKey, mLockTimeOut);
boolean result = false;
try {
result = delegate().put(aKey, aValue);
} finally {
mLocks.releaseWriteLock(aKey);
mLocks.releaseReadLock(mPublicKey);
}
return result;
}清除行动
public void clear() {
mLocks.acquireWriteLock(mPublicKey, mLockTimeOut);
try {
delegate().clear();
} finally {
mLocks.releaseWriteLock(mPublicKey);
}
}ResourceLockManager码
Striped<ReadWriteLock> lockCache = Striped.lazyWeakReadWriteLock(DEFAULT_PARTITIONS);acquireReadLock
lockCache.get(aKey).readLock().lock()releaseReadLock
lockCache.get(aKey).readLock().unlock();acquireWriteLock
lockCache.get(aKey).writeLock().lock()releaseWriteLock
lockCache.get(aKey).writeLock().unlock();在实现了公钥的读/写锁以处理清楚的方法情况后,我开始面临以下问题:
Exception in thread "pool-5-thread-10" java.lang.IllegalMonitorStateException: attempt to unlock read lock, not locked by current thread
at java.util.concurrent.locks.ReentrantReadWriteLock$Sync.unmatchedUnlockException(ReentrantReadWriteLock.java:444)
at java.util.concurrent.locks.ReentrantReadWriteLock$Sync.tryReleaseShared(ReentrantReadWriteLock.java:428)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.releaseShared(AbstractQueuedSynchronizer.java:1341)
at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.unlock(ReentrantReadWriteLock.java:881)
at com.google.common.util.concurrent.ForwardingLock.unlock(ForwardingLock.java:48)
at org.multimap.rt.locks.ResourceLockManager.releaseReadLock(ResourceLockManager.java:97)
at org.multimap.rt.util.ConcurrentMultiMap.put(ConcurrentMultiMap.java:81)
at org.multimap.rt.util.OneShotTask.run(ConcurrentMultiMapTest.java:233)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)上面的问题不仅是为了放,它有时也是在移除期间,它不是总是来的。就好像每3-4次就有一次。
另一个观察-为了测试并发性,如果我们创建了44个或更少的线程,那么我就不会在本地系统中看到这个问题。一到45岁或更多,我就开始看到这个例外。
单元测试代码:
public void TestConcurrentMultiMap() throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(45);
for (int i = 0; i < 45; i++) {
int num = (int) Math.round(Math.floor(Math.random() * 3));
int oprn = (int) Math.round(Math.random());
executor.execute(new OneShotTask(String.valueOf(num), myMap1, oprn));
}
executor.shutdown();
executor.awaitTermination(1000L, TimeUnit.MILLISECONDS);
}
class OneShotTask implements Runnable {
String str;
Multimap mMap;
int mOprn;
OneShotTask(String s, Multimap aMap, int oprn) {
str = s;
mOprn = oprn;
mMap = aMap;
}
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if(mOprn == 0) {
mMap.put("key", "value" + str );
} else {
mMap.remove("key", "value" + str );
}
}
}发布于 2022-12-02 10:00:59
看起来Striped.lazyWeakReadWriteLock()中有一个bug。通过将初始化从Striped.lazyWeakReadWriteLock更改为Striped.readWriteLock(),我无法再现它。
https://stackoverflow.com/questions/74610227
复制相似问题