当前位置: 首页 > 面试题库 >

最终字段和线程安全

江永安
2023-03-14
问题内容

为了线程安全,是否应该是故意不可变的Java类’final’的所有字段(包括超字段),还是没有修饰符方法就足够了?

假设我有一个带有非最终字段的POJO,其中所有字段都是某种不可变类的类型。这个POJO有getters-
setters和一个设置一些初始值的构造函数。如果我通过敲除修饰符方法来扩展此POJO,从而使其不可变,那么扩展类是否是线程安全的?


问题答案:

为了以final线程安全的方式使用没有字段的有效不可变对象,在初始化后使对象可用于其他线程时,需要使用一种安全的发布习惯用法,否则这些线程可以看到处于部分初始化状态的对象(来自Java并发在实践中):

  • 从静态初始化程序初始化对象引用;
  • 将对它的引用存储到volatile字段或AtomicReference中;
  • 将对它的引用存储到适当构造的对象的最终字段中;要么
  • 将对它的引用存储到由锁适当保护的字段中。

将不可变对象的字段声明为as
final会释放此限制(即,如果其他线程看到对该对象的引用,它们也final将以完全初始化的状态看到其字段)。但是,通常情况下,它不能保证其他线程可以在对象发布后立即看到对该对象的引用,因此您可能仍需要使用安全发布来确保对该对象的引用。

请注意,如果您的对象实现了接口,则可以使用Collections.unmodifiableList(),等使用的方法:

class ImmutableFooWrapper implements IFoo {
    private final IFoo delegate; // final provides safe publication automatically

    public ImmutableFooWrapper(IFoo delegate) {
        this.delegate = delegate;
    }
    ...
}

public IFoo immutableFoo(IFoo foo) {
    return new ImmutableFooWrapper(foo);
}


 类似资料:
  • 我们正在开发基于spring boot 2.5.6的支付应用程序。该应用程序托管在docker上,并在Java14上启动。我们创建了一个名为的抽象类,它是,包含两个变量和。所有枚举类都扩展了这个基类,并在其中定义常量。 这个决定是为了定制整个应用程序层中使用的枚举。你可以在下面看到一个例子: 该类在实体层中用作嵌入变量,如下所示: 系统工作得很好,但是发生了一些错误,ShapeEnum的字段。RE

  • 问题内容: 在Java中进行序列化后,是否可以将字段设置为任何非默认值?我的用例是一个缓存变量- 这就是为什么。我也有一个习惯,即不要更改字段(即,地图的内容已更改,但对象本身保持不变)。但是,这些属性似乎是矛盾的- 尽管编译器允许这样的组合,但除反序列化之后,我无法将字段设置为任何值。 我尝试了以下操作,但没有成功: 简单的字段初始化(如示例所示):这是我通常所做的,但是在未序列化之后似乎没有发

  • 问题内容: 我试图简单地测试JLS保证的最终字段的初始化安全性。这是我写的论文。但是,根据我当前的代码,我无法使其失败。有人可以告诉我我做错了什么吗,或者这只是我必须一遍又一遍然后看到失败的时机而已? 这是我的代码: 我的线程正在这样调用它: 我已经多次运行过这种情况。我当前的循环产生了10,000个线程,但是我已经完成了1000、100000,甚至一百万个线程。仍然没有失败。我总是看到3和4这两

  • 问题内容: 说我们有这个 是什么使该线程不安全?接下来是这个问题。 问题答案: 一旦安全发布,它就是线程安全的。例如,此程序可能会打印“不安全”(它可能不会使用hotspot / x86的组合)-如果您进行最终定格,则不会发生:

  • 问题内容: 我已经阅读了很多,但是还没有找到确切的答案。 我有一堂课,看起来像这样: 而且我想知道从Foo实例访问sharedData是否是线程安全的(如构造函数和doSomethingUseful()中所示)。Foo的许多实例将在多线程环境中创建。 我的意图是在静态初始化程序中初始化sharedData,此后不进行修改(只读)。 我读到的是,不可变对象本质上是线程安全的。但是我仅在实例变量的上下

  • 代码: 当我同时执行两个请求时,执行的结果是: Mozilla/5.0(Windows NT 6.1; WOW64; rv: 26.0)Gecko/20100101 Firefox/26.0 Mozilla/5.0(Windows NT 6.1; WOW64)AppleWebKit/537.36(KHTML,像壁虎)Chrome/32.0.1700.102Safari /537.36 Mozill