让事情变得简单: 通常 update() 由多个线程执行。 一旦这是真的 if(!isSplit && users.size() >= Constants.SPLIT_THRESHOLD) 我希望当 split() 函数被单元化时没有人执行 update() 方法。
public class Cell {
private ConcurrentHashMap<Integer, User> users;
private ConcurrentHashMap<Long, Cell> subCells;
private boolean isSplit;
private Lock splitLock;
public Set<Integer> update(User user){
//code executed by 1 thread
if(!isSplit && users.size() >= Constants.SPLIT_THRESHOLD)
{
splitLock.lock();
{
try
{
split();
isSplit = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
finally
{
splitLock.unlock();
}
}
}
// code executed by multiple threads
// on users hashmap
}
private void merge(){}
private void split(){}
}
最佳答案
当锁定写入/更新时,一般模式是首先获取锁,然后检查条件(由写入/更新修改),然后写入。
lock
if(x) {
write/update
}
unlock
与此对比,它类似于您发布的代码:
if(x) {
lock
write/update
unlock
}
对于线程 1,x 可以计算为 true,同时线程 2 执行写入/更新,导致 x 计算为 false,但线程 1 已经在条件内,并且无论如何都会执行写入/更新。失败。
更新:回答更新的问题。
查看 ReentrantReadWriteLock 的 javadoc。
您可能希望使用写锁隔离您的 split() 方法(只有一个线程可以获取),并使用读锁隔离您的 update 方法的其余部分(多个线程可以获取,只要没有人拥有写锁)锁)。
关于java - 关键部分: be sure that this method is executed by only 1 thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18514134/