不一致的同步违规

时间:2014-10-22 17:27:02

标签: java multithreading sonarqube findbugs

我在return语句中通过以下方法获得了此违规行为:

protected Token getAccessToken() {  
    synchronized (this) {
        if (token == null || isExpired(token))
            token = createToken();
    }

    return token; // <-- Inconsistent synchronization of blablabla.token; locked 75% of time
}

是否存在与token字段相关的可见性问题?据我所知,synchronized块令牌后应该有最新的值。

我错过了什么或是假阳性吗?

2 个答案:

答案 0 :(得分:4)

请考虑以下事项:

  • Thread1:进入方法
  • Thread2:进入方法
  • Thread1:进入同步块,令牌不为空且未过期
  • Thread1:退出同步块
  • 线程2:进入同步块,令牌不为空但已过期
  • Thread2:分配新令牌
  • Thread1:返回令牌(可能是线程2指定的新值,可能是旧值)
  • Thread2:退出同步块
  • Thread2:返回(新)令牌

如果你想做你正在做的事情,那么token可能需要是易变的(但这可能不是一个充分的保证!),或者你应该总是从synchronized块中返回值,或者分配token的值为synchronized块内的局部变量,并从外部返回该局部变量。

在此期间,这甚至没有考虑其他方法可能正在做什么。如果另一个(同步或非同步)方法也修改了token(例如,指定null),那么您可能会因为假设 token而更糟糕not null(正如您刚刚检查过的那样),而实际上它可能是null 现在

答案 1 :(得分:3)

线程A可能会返回刚刚由线程B重新创建的令牌,因为令牌已过期。

因此,线程B将从同步块中写入令牌,但线程B将从未同步的块中读取它。所以是的,可能会有问题。返回应该在同步块内。