Java 具有完全未来的可重入锁定
在CompletableFuture出现之前,如果我想锁定一个变量,我可以这样做:Java 具有完全未来的可重入锁定,java,multithreading,locking,completable-future,reentrantlock,Java,Multithreading,Locking,Completable Future,Reentrantlock,在CompletableFuture出现之前,如果我想锁定一个变量,我可以这样做: private ReentrantLock myLock = new ReentrantLock(); private List<UUID> myLockableList = new ArrayList<>(); public void doStuff() { try { myLock.lock(); myLockableList.
private ReentrantLock myLock = new ReentrantLock();
private List<UUID> myLockableList = new ArrayList<>();
public void doStuff()
{
try
{
myLock.lock();
myLockableList.clear();
}
finally
{
if (myLock.isLocked())
{
myLock.unlock();
}
}
}
private ReentrantLock myLock=new ReentrantLock();
私有列表myLockableList=新建ArrayList();
公共空间
{
尝试
{
myLock.lock();
myLockableList.clear();
}
最后
{
if(myLock.isLocked())
{
myLock.unlock();
}
}
}
(显然,这是一个非常简化的示例,我还有其他方法尝试对myLockableList进行操作)
根据ReentrantLock,将出现3种情况中的1种:
- 如果锁未被另一个线程持有,则获取锁并立即返回,将锁持有计数设置为1
- 如果当前线程已经持有锁,那么持有计数将增加1,并且方法立即返回
- 如果锁由另一个线程持有,则当前线程出于线程调度目的将被禁用,并处于休眠状态,直到获得锁为止,此时锁持有计数设置为1
private ReentrantLock myLock = new ReentrantLock();
private List<UUID> myLockableList = new ArrayList<>();
public CompletionStage<Void> doStuff()
{
return CompletableFuture.runAsync(() -> {
try
{
myLock.lock();
myLockableList.clear();
}
finally
{
if (myLock.isLocked())
{
myLock.unlock();
}
}
});
}
private ReentrantLock myLock=new ReentrantLock();
私有列表myLockableList=新建ArrayList();
公共完成阶段doStuff()
{
返回CompletableFuture.runAsync(()->{
尝试
{
myLock.lock();
myLockableList.clear();
}
最后
{
if(myLock.isLocked())
{
myLock.unlock();
}
}
});
}
我希望未来的行为也会如此。但是,CompletableFuture可能会使用一个新线程执行上述操作,或者(如果我的理解正确的话)可能会使用一个已经在使用的线程。如果发生第二种情况(被重用的线程已经获得了锁),那么我的锁不会暂停线程并等待锁,相反,它可能会立即返回(看起来它已经获得了锁)
我似乎在文档中找不到明确的答案。我对形势的理解正确吗?如果是这样,那么在使用CompletableFuture时,我们应该如何锁定资源
非常感谢你的建议 除了评论中推荐的内容外,还有很多值得一读的信息
例如:
ReentrantLock属于上次成功锁定但尚未解锁的线程
您的示例使用,Javadoc说您不应该这样做:
此方法设计用于监视系统状态,而不是用于同步控制
最后,Javadoc包含一个很好的使用示例,在“try”块中显示lock()
,在“Finally”块中显示unlock()
建议在调用后立即使用try块锁定,最典型的是在构建之前/之后,例如:
“它可能使用已在使用的线程”。不,可能不会,因为线程正在使用中。它可能使用一个空闲线程,该线程将尝试正常获取锁。您的
finally
子句错误,您不应该检查isLocked()
。您可以在try
的开头使用lock()
,在finally
子句中使用unlock()
。没有如果。好的,谢谢。所以我的理解是不正确的:)所以我对锁定没有问题。好吧,你是这样做的(使用isLocked()
),所以你可能想看看这个,我会看一看-谢谢,W.R.TisLocked()
,我在lock()
之前有一个方法处理一些东西,这取决于结果,可能意味着lock()
未被调用。发生这种情况时,调用unlock()
会引发非法异常。我本可以使用嵌套的try-finally块,但那会变得混乱isLocked()
的常见(尽管非常罕见)用例是与tryLock()一起使用的。更好的方法是使用更高级别的并发原语,这样就不需要处理原始锁。我建议您阅读并发教程。我同意您所说的一切-我在没有首先查找的情况下将isLocked()
方法放进去了。我真正的误解来自于思考完整的未来。
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}