- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有这样的东西:
private Striped<ReadWriteLock> stripes = Striped.lazyWeakReadWriteLock(STRIPES_AMOUNT);
private final Cache<Long, BlockingDeque<Peer>> peers = CacheBuilder.newBuilder()
.expireAfterWrite(PEER_ACCESS_TIMEOUT_MIN, TimeUnit.MINUTES)
.build();
每次对缓存进行操作时,我都会在stripes
的帮助下锁定它。
example#1 [写操作]
public void removePeers(long sessionId) {
Lock lock = stripes.get(sessionId).writeLock();
lock.lock();
try {
peers.invalidate(sessionId);
} finally {
lock.unlock();
}
}
示例#2 [读取操作]
public BlockingDeque<Peer> getPeers(long sessionId) {
Lock lock = stripes.get(sessionId).readLock();
lock.lock();
try {
return peers.getIfPresent(sessionId);
} finally {
lock.unlock();
}
}
example#3 [写操作]
public boolean addPeer(Peer peer) {
long key = peer.getSessionId();
Lock lock = stripes.get(key).writeLock();
lock.lock();
try {
BlockingDeque<Peer> userPeers = peers.getIfPresent(key);
if (userPeers == null) {
userPeers = new LinkedBlockingDeque<Peer>();
peers.put(key, userPeers);
}
return userPeers.offer(peer);
} finally {
lock.unlock();
}
}
问题: 锁定下面的方法最有效的方法是什么?
/**
* I should get the whole peers in cache
*/
public BlockingDeque<Peer> getAllPeers() {
BlockingDeque<Peer> result = new LinkedBlockingDeque<Peer>();
for (BlockingDeque<Peer> deque : peers.asMap().values()) {
result.addAll(deque);
}
return result;
}
最佳答案
最有效的方法就是根本不锁定:)
请参阅 Code Review 中我更新的答案:你不需要 ReadWriteLock
,因此您不需要锁定读取。
当您读取时(例如在线程 1 中),您会获得当时缓存中内容的快照。如果您有并发修改(在线程 2 中),即使您使用锁,缓存的内容也可能在线程 1 完成其计算之前已更改,并且锁不会为您购买任何内容:
Thread 1 Thread 2
| |
getAllPeers |
| addPeer
Do something with |
the Peers but not |
the added one |
| |
所以你的 getAllPeers()
的实现就这样就好了。
作为旁注,如果您需要将所有条纹锁定在 Striped<Lock>
中,你可以使用 getAt()
来做到这一点,但是如果 lock()
之一,这种幼稚的方法可能会给您带来麻烦。调用抛出未经检查的异常( which is permitted ):
for (int i = 0, size = stripes.size(); i++; i < size) {
stripes.getAt(i).lock();
}
try {
// Do something
} finally {
for (int i = 0, size = stripes.size(); i++; i < size) {
stripes.getAt(i).unlock();
}
}
另一种方法是递归地执行此操作,但它会根据 strip 的数量增加堆栈的长度,因此您可以获得 StackOverflowException
如果您有大量条纹:
public void doSomethingWithLocks() {
doSomethingWithLock(0);
}
private void doSomethingWithLock(int stripe) {
if (stripe < stripes.size()) {
Lock lock = stripes.getAt(stripe);
lock.lock();
try {
doSomethingWithLock(stripe + 1);
} finally {
lock.unlock();
}
} else {
doSomething();
}
}
private void doSomething() {
// Do something
}
关于java - Cache<K, BlockingDeque<V>> 与 Striped<Lock> 组合 : how to lock the whole cache,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22156155/
我很茫然。我有一个 BlockingDeque private class Consumer extends Thread { @Override public void run()
Deque public interface Deque extends Queue 1、 一个线性collection,支持在两端插入和移除元素; 2、 既支持有容量限制的双端队列,也
我有这样的东西: private Striped stripes = Striped.lazyWeakReadWriteLock(STRIPES_AMOUNT); private final Cach
我是一名优秀的程序员,十分优秀!