当前位置: 首页 > 知识库问答 >
问题:

Java并发-发布不可变对象(实践中的Java并发)

荣晨朗
2023-03-14
    null
public static List<ImmutableObject> list = new ArrayList<ImmutableObject>();

// thread A invokes this method first
public static void methodA () {
    list.add(new ImmutableObject());
}

// thread B invokes this method later
public static ImmutableObject methodB () {
    return list.get(0);
}
@NotThreadSafe
public class UnsafeLazyInitialization {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null)
            resource = new Resource();  // unsafe publication
        return resource;
    }
}

对于此问题的第二部分,将在另一个问题(单击此处)中详细讨论

共有1个答案

班言
2023-03-14

是的,你是正确的,有一场数据竞赛。

只有ImmutableObject是不可变的,并且可以在线程之间安全共享,但是列表没有这些相同的保证,因此在添加ImmutableObject和检索它之间存在数据竞争。

在JCIP中,作者的意思是不可变对象可以安全地发布,因为您不必担心制作防御性副本之类的事情。

 类似资料:
  • 问题内容: 在《 Java Concurrency In Practice》中,作者指出 不变对象可以通过任何机制发布 不可变对象可以在没有附加同步的情况下被任何线程安全地使用,即使不使用同步来发布它们。 这是否意味着以下成语可以发布不可变对象? 会有数据竞赛吗?(这意味着线程B可能无法在线程A添加的列表中看到不可变对象) 非常感谢你。 此外,作者说,如果Resource是不可变的,以下代码是安全

  • 不可变对象(Immutable Objects) 如果一个对象它被构造后其,状态不能改变,则这个对象被认为是不可变的(immutable )。不可变对象的好处是可以创建简单的、可靠的代码。 不可变对象在并发应用种特别有用。因为他们不能改变状态,它们不能被线程干扰所中断或者被其他线程观察到内部不一致的状态。 程序员往往不愿使用不可变对象,因为他们担心创建一个新的对象要比更新对象的成本要高。实际上这种

  • 问题内容: 我对上面的示例有一个疑问,该示例是从 练习 清单14.12计数使用锁实现的信号量的 Java并发中 提取的。 我想知道为什么我们需要在构造函数中获取锁(如所示的lock.lock()被调用)。据我所知,构造函数是 原子的 (引用转义除外),因为没有其他线程可以获取该引用,因此,其他线程看不到一半构造的对象。因此,我们不需要构造函数的同步修饰符。此外,只要对象被安全发布,我们也不必担心

  • 我对上面的示例有一个问题,该示例是从Java并发实践清单14.12使用锁实现的计数信号量中提取的。 我想知道为什么我们需要获取构造函数中的锁(如图所示lock.lock()被调用)。据我所知,构造函数是原子的(除了引用转义),因为没有其他线程可以获得引用,因此,半构造对象对其他线程不可见。因此,我们不需要构造函数的同步修饰符。此外,我们也不需要担心内存可见性,只要对象安全发布。 那么,为什么我们需

  • 问题内容: Brian Goetz的Java Concurrency in Practice提供了一个有效的可伸缩缓存供并发使用的示例。这是该类的代码: 可能是个愚蠢的问题,但有人能告诉我该类的并发用法吗?喜欢在主? 干杯,Agata 问题答案: 这是一个计算阶乘的示例: 因此,如果两个线程尝试在完全相同的时间计算相同的阶乘,则由于线程安全,因此只有其中一个将实际执行计算。第二个线程将简单地获取第

  • 由于引用字段lastLogin没有任何字段的属性来保证可见性(final、volatile、guarded或由静态初始化器初始化),我认为映射本身可能不会以完全构造的状态显示给其他线程,因此本末倒置。还是我错过了什么?