edu*_*edu 1 java spring java-threads
那些开发过专业的多线程 Java Spring 应用程序的人可能可以证明 volatile 关键字的使用几乎不存在(以及与此相关的其他线程控制),尽管在需要时错过它可能会带来灾难性的后果。
让我提供一个非常常见的代码示例
@Service
public class FeatureFlagHolder {
private boolean featureFlagActivated = false;
public void activateFeatureFlag() {
featureFlagActivated = true;
}
// similar code to de-activate
public boolean isFeatureFlagActivated() {
return featureFlagActivated;
}
}
Run Code Online (Sandbox Code Playgroud)
假设改变和读取状态的线程featureFlagActivated不同。AFAIK,读取布尔值的线程可以根据 JVM 缓存其值并且从不刷新它。在实践中,我从未见过这种情况发生。事实上,我什至从未见过布尔值在读取时没有立即更新。
这是为什么?
在最基本的层面上,必须说缺乏并volatile 不能保证它会失败。它只是意味着允许 JVM 进行可能导致失败的优化。但这些优化是否发生以及是否会导致失败受到许多不同因素的影响。因此,通常很难真正发现这些问题,直到它们变成灾难性的。
首先,我想总结一下当出现问题时经常发生的情况。
请注意,并非所有这些都是必要的,但当我实际观察该问题时,它们往往是正确的。
我个人的解释(加上一些关于该主题的阅读)引导我得出以下经验法则:
仅凭这三个因素就很难真正发现问题,除非在非常极端的情况下(即执行太多会导致系统严重崩溃)。
在您的具体示例中,我假设功能标志不会每秒切换多次。它更有可能是每个进程设置一次,然后保持不变。
例如,如果您在同一秒内有多个传入请求,并且在切换功能标志的那一秒中途有多个传入请求,则可能会发生切换后发生的某些请求仍将使用旧值,因为它是从之前缓存的。
你会注意到吗?不太可能。很难区分“此请求是在更改之前传入的”与“此请求是在更改之后传入的,并且错误地使用了旧值”。如果 10 个请求中有 6 个使用旧值,而不是 10 个请求中的 5 个使用正确的值,那么很可能没有人会注意到。
| 归档时间: |
|
| 查看次数: |
366 次 |
| 最近记录: |