Ror*_*ory 6 java singleton spring spring-mvc thread-safety
我有一个单独的Spring bean(默认范围).因此,多个线程将使用一个实例.但是,我对线程安全有点困惑,显然所有Spring bean都是线程安全的,如果它们是无状态的,但我的bean不是无状态的,它有各种实例变量,每个请求/其他控制器/类使用它们.
这是我的单例bean的开头:
public class PcrfSimulator {
private final CustomGxSessionIdCacheImpl gxSessionIdCache = new CustomGxSessionIdCacheImpl();
private final PcrfRecord pcrfRec = new PcrfRecord();
private final ResponseConditions responseConditions = new ResponseConditions();
public CustomGxSessionIdCacheImpl getGxSessionIdCache() {
return gxSessionIdCache;
}
public ArrayList<Rule> getRules() {
return pcrfRec.getRules();
}
Run Code Online (Sandbox Code Playgroud)
因此,上面的字段将由多个线程访问 - 是否足以将这些字段标记为易失性,或者我是否必须标记访问它们的方法(不仅有这个类,而且其他控制器/类有很多)以及同步和使用等待/通知等?
非常感谢!
volatile没有帮助。它只会确保该值确实更新。
易失性意味着(http://www.javamex.com/tutorials/synchronization_volatile.shtml):
- 该变量的值永远不会在线程本地缓存:所有读取和写入都将直接进入“主内存”;
- 对变量的访问就像将其包含在同步块中一样,并对其自身进行同步。
仅当您的控制流在第一次写入和最后一次读取共享变量之间从不退出(外部)同步块,并且所有共享变量仅在使用同一锁对象的同步块内访问时,使方法同步才会有帮助。
所以一般的解决方案是在这种情况下防止共享变量。使类不可变的一种简单方法是使用局部变量和方法参数而不是共享实例变量。
您写道“如果 Spring bean 是无状态的,那么它们就是线程安全的,但我的 bean 不是无状态的。” ——好的,这个主题已在上面的段落中讨论过。
但从你的代码来看,这不是问题!变量用 标记,final因此它们是不可变的。如果该对象的字段以相同的方式运行(未更新或充分防止并发修改问题),则没有可变共享变量。有时这被称为“有效无状态”。这意味着这些值没有改变。所以这对于并发来说不是问题(因为并发问题是关于改变值的)。
最后:如果字段 ( PcrfRecord...) 是有效无状态的,则您可以在不同线程中使用示例中的这个有效无状态类,而无需同步块。(如果字段PcrfRecord...不是无状态的,那么该类PcrfSimulator就不能称为有效的无状态)——但这与 Spring 无关,它是普通的 Java。
顺便说一句:如果您的变量是,final则不需要创建它们volantile。