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

不变性可以确保线程安全吗?

曾晨
2023-03-14
问题内容

好吧,考虑Immutable下面给出的不可变类:

public final class Immutable
{
    final int x;
    final int y;
    public Immutable(int x,int y)
    {
        this.x = x;
        this.y = y;
    }
    //Setters
    public int getX()
    {
        return this.x;
    }
    public int getY()
    {
        return this.y;
    }
}

现在,我正在Immutable一个类中创建一个对象,Sharable该对象的对象将由多个线程共享:

public class Sharable
{
    private static Immutable obj;
    public static Immutable getImmutableObject()
    {
        if (obj == null) --->(1)
        {
            synchronized(this)
            {
                if(obj == null)
                {
                    obj = new Immutable(20,30); ---> (2)
                }
            }
        }
        return obj; ---> (3)
    }
}

Thread A看到objas null并移入同步块并创建对象。现在,由于
Java内存模型(JMM)允许多个线程在初始化开始之后但尚未结束之前观察对象 因此,Thread B可以将写入操作obj视为在写入的字段之前发生Immutable。因此,因此Thread B可以看到部分构造Immutable,该构造很可能处于无效状态,并且其状态以后可能会意外更改。

它不是Immutable非线程安全的吗?

编辑
好,在仔细研究了SO并进行了一些评论之后,我知道 您可以 在构造对象之后 安全地在线程之间共享对不可变对象的引用
。另外,如@Makoto所述, 通常需要声明包含其引用的字段为volatile,以确保可见性
。另外,如@PeterLawrey所述,将对不可变对象的引用声明为,final使字段为thread-safe


问题答案:

因此,线程B可以看到对objas的写入发生在对Immutable字段的写入之前。因此,线程B可能因此看到部分构造的不可变,该不可变很可能处于无效状态,并且其状态以后可能会意外更改。

在Java 1.4中,这是正确的。在Java 5.0及更高版本中,构造后的final字段是线程安全的。



 类似资料:
  • 关于一次从多个线程访问局部变量的几个问题: > < li> 我有多个线程写入和读取变量值,我是否应该同步访问它? 变量每隔几秒钟从 Thread1 更新一次,每隔几秒钟从 Thread2 读取和更新到数据库。 如果我没有任何逻辑并且没有任何并发问题,会出现哪些问题? 我应该为此使用volatile吗? 编辑: 我想强调的是,我没有任何并发问题。这是我的具体方案: 一个。我的变量名称是 ,它测量 p

  • 我得到的是它们是线程安全的。 杰里米·曼森博客的片段- 因为this引用存储在lastconstructed中“,因此转义构造函数 请建议。

  • 类OneValueCache是不可变的。但是我们可以更改变量缓存的引用。 但我不能理解为什么VolateCachedFactorizer类是线程安全的。 对于两个线程(线程A和线程B),如果线程A和线程B同时到达,那么两个线程A和B都将尝试创建OnEvalueCache。然后线程A到达而线程B同时到达。然后线程A将创建一个,它覆盖threadB创建的值(OneValueChange是不可变的,但是

  • 1.1 定义 线程安全:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协调,这个类都能表现出正确的行为,那么就称这个类是线程安全的。 线程不安全:如果一个类对象同时可以被多个线程访问,如果不做同步处理,可能表现出线程不安全现象(抛出异常、逻辑错误)。 1.2 原子性 1.2.1 定义提供了互斥访问,同一时刻(时间段)只能有一

  • 问题内容: 是否有任何书面证明的线程安全保证?javadoc暗示了它,但没有直接解决它: 返回字符串对象的规范表示。最初为空的字符串池由String类私有维护。 调用intern方法时,如果池已经包含等于equals(Object)方法确定的此String对象的字符串,则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。 因此,对于任意两个字符串s和t,当且