【问题标题】:SonarIssue: Does not release lock on all pathsSonarIssue:不释放所有路径上的锁定
【发布时间】:2020-09-16 12:33:08
【问题描述】:

我有类似下面提到的代码。我正在释放 finally 块中的锁定,但 sonarqube 仍然显示“不释放所有路径上的锁定”消息。 我尝试将 lock.isHeldByCurrentThread() 更改为 lock.isLocked() 但仍然没有运气。而且我没有在任何其他方法中使用锁定。不知道如何解决这个声纳问题。

class Sample{
    ReentrantLock lock = new ReentrantLock();

    public Response<T> method(Inputs input){

        try{
            // some logic
            lock.lock();

        }catch(Exceptions e){
            // handle exception
        }finally{
            if(lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }
}

【问题讨论】:

  • 但我也检查了 if(lock.islocked()) 。此条件检查所有线程。

标签: java sonarqube locking reentrantlock


【解决方案1】:

Sonar 在这里看到的是,您正在无条件地获取锁,然后仅在某些条件下释放它。 Sonarqube 无法判断未释放锁的路径被选择的可能性有多大,它只是认为它可能发生。

另外请注意,您用于检查锁的这些方法似乎不适用于此用途。例如ReentrantLock#isHeldByCurrentThread 的文档说:

此方法通常用于调试和测试。

这似乎是一个警告,您应该在此处重新考虑使用它。

看起来这段代码使用这个方法是为了区分在获取锁之前抛出异常的情况和已经获取锁的情况,因此它可以知道是否需要释放锁。

答案不是用什么方法来测试锁是否被获取,而是修复代码,这样就不需要测试了。添加另一个 try-block,如下所示:

class Sample{
    ReentrantLock lock = new ReentrantLock();

    public Response<T> method(Inputs input){

        try{
            // do whatever needs doing prior to acquiring lock
            lock.lock();
            try {
                // do whatever needs doing with lock held
            } finally {
                // release lock on the way out of inner try block
                lock.unlock();
            }
        } catch (Exception e){
            // handle exception thrown from anywhere within outer or inner try block
        }
    }
}

这样,如果执行进行到获得锁的程度,它将在退出时被释放。如果在任何地方抛出异常,它将被捕获,并且锁将被解锁。

TLDR:如果你无条件获取锁,那么你应该无条件释放它。

【讨论】:

  • 这个答案很棒。顺便说一句,您真的不应该将isHeldByCurrentThread() 用作“真实”程序逻辑的一部分。它有时在诊断逻辑中很有用,但如果您发现自己在实际代码流中使用它,您应该仔细重新检查该代码。
  • @jtahlborn:谢谢。绝对 api 文档支持这种观点,并将其纳入答案。我一直在犹豫是否要包括它。
猜你喜欢
  • 2021-03-09
  • 2018-03-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-23
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
  • 2011-03-17
相关资源
最近更新 更多