我正在编写一个需要线程安全的类。遵循并发编程的原则之一,我正在尝试尽可能使实例变量最终化。
问题在于由于使用DI框架(在本例中为Spring),我经常不能使用final关键字。例如在带有@PostConstruct
批注的方法中设置的任何变量都不能为最终变量。另外,任何带有@Value
批注的变量也不能是最终变量。
我希望存在一个@EffectivelyFinal
注释。创建仅出于文档目的而没有功能存在的对象相对来说比较琐碎。但是,我希望已经存在一种解决方案,如果注释在第一次分配变量后检测到您试图为该变量赋值,则注释会使编译器失败。
请问有人知道这样的解决方案吗?
答案 0 :(得分:0)
IMO,您在这里有些困惑。使对象不可变本质上使其成为线程安全的:无状态,无需同步。将 all 字段设置为最终字段将确保该对象被安全发布;即:读取/观察对新创建实例的引用的线程将看到通过其构造函数和设置的所有变量均为最终变量。
设置“某些”实例字段final
不会给您带来任何帮助。 JLS提供的有关安全发布实例的保证。
您仍然可以拥有一个线程安全对象,该对象具有通过setters/getters
更新的字段,但是这些字段将受到例如某些锁的保护。
@Value
和/或@PostConstruct
方法应该只被调用一次-并且Spring控制没有其他业务逻辑方法被调用(甚至没有完全创建上下文)到该实例中(尽管如果您真的想要的话,可以破解这个)。但是也应该从另一个角度考虑:通常spring返回单例豆(毕竟您使用的是@Value
),因此在这些情况下具有 any 状态仍然需要仔细的推理,并且很可能无论如何还是线程安全的访问。
或者通常是 您通过@PostConstruct
添加某种服务(这些服务依赖于构造函数中设置的服务),该服务应该是无状态的;而带有@Value
批注的字段是private
-因此根本不会公开(没有设置器),因此 并不是在考虑线程安全性时不变的理由。