gpt4 book ai didi

java - Cache> 与 Striped 组合 : how to lock the whole cache

转载 作者:行者123 更新时间:2023-12-01 13:19:32 28 4
gpt4 key购买 nike

我有这样的东西:

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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com