SonarIssue: 在所有路径上未释放锁

huangapple go评论82阅读模式
英文:

SonarIssue: Does not release lock on all paths

问题

我有类似下面提到的代码。我在 finally 块中释放了锁,但 SonarQube 仍然显示 "Does not release lock on all paths" 的信息。
我尝试将 lock.isHeldByCurrentThread() 更改为 lock.isLocked(),但仍然没有成功。而且我在任何其他方法中都没有使用这个锁。不知道如何解决这个 Sonar 问题。

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();
            }
        }
    }
}
英文:

I have code something like below mentioned. I am releasing the lock in finally block but still sonarqube is showing "Does not release lock on all paths" message.
I tried changing lock.isHeldByCurrentThread() to lock.isLocked() but still no luck. And I am not using lock in any other methods. No clues how to fix this sonar issue.

class Sample{
    ReentrantLock lock = new ReentrantLock();

    public Response&lt;T&gt; method(Inputs input){

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

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

答案1

得分: 1

以下是翻译好的内容:

Sonar看到的是你在无条件地获取锁,然后只有在某些条件下才释放它。Sonarqube无法判断锁没有被释放的路径被选择的可能性有多大,它只是看到可能发生这种情况。

还要注意,看起来你正在使用的这些检查锁的方法并不适合这种用法。例如,ReentrantLock#isHeldByCurrentThread 的文档中写道:

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

这似乎是一个警告,你应该重新考虑是否应该像你在这里做的这样使用它。

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

答案不是使用哪种方法来测试锁是否被获取,而是修复代码,使得不需要进行这种测试。可以再添加一个try块,像这样:

class Sample{
    ReentrantLock lock = new ReentrantLock();

    public Response<T> method(Inputs input){

        try{
            // 获取锁之前需要执行的操作
            lock.lock();
            try {
                // 持有锁时需要执行的操作
            } finally {
                // 在内部try块退出时释放锁
                lock.unlock();
            }
        } catch (Exception e){
            // 处理从外部或内部try块中抛出的异常
        }
    }
}

这样,如果执行进展到获取锁的地方,它会在退出时释放锁。如果在任何地方抛出异常,它将被捕获,锁将被解锁。

简而言之:如果你无条件地获取锁,那么你应该无条件地释放它。

英文:

What Sonar sees here is that you are acquiring a lock, unconditionally, then releasing it only on some condition. Sonarqube can't tell what the likelihood is that the path where the lock isn't released will ever be chosen, it just sees it could possibly happen.

Also be aware it looks like these methods you're using to check the lock aren't intended for this usage. For instance the documentation for ReentrantLock#isHeldByCurrentThread says:

> this method is typically used for debugging and testing.

which seems like a warning that you should reconsider using it as you're doing here.

It looks like this code is using this method in order to distinguish between the case where an exception is thrown before the lock is acquired, vs the case where the lock has already been acquired, so it can know whether it needs to release the lock.

The answer isn't what method to use to test the lock to see if it is acquired, it is to fix the code so the need for the test doesn't come up. Add another try-block, like this:

class Sample{
    ReentrantLock lock = new ReentrantLock();

    public Response&lt;T&gt; 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
        }
    }
}

This way if execution progresses to the point that the lock gets acquired, it will get released on the way out. If an exception gets thrown anywhere, it will get caught, and the lock will be unlocked.

TLDR: If you acquire a lock unconditionally, then you should release it unconditionally.

huangapple
  • 本文由 发表于 2020年9月16日 20:33:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63920184.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定