Java中的AtomicReference - 在线程安全环境中设置引用所必需的?

在Java中存在AtomicReference类。这是否意味着设置引用本身并不是原子操作? 例如,这是不是线程安全的(假设返回的值不能被修改)?:
public void someMethod()
{
   this.someList = Collections.unmodifiableList(new LinkedList<Object>());
}

public List<Object> getReadOnlyList()
{
   return someList;
}
在C#怎么样?     
已邀请:
根据Java语言规范3.0版,第17.7节:   写给   并且引用的读取始终是原子的,无论它们是否已实现   为32位或64位值。 AtomicReference可以执行比较并设置为原子操作。 这不是线程安全的:
public boolean changeList(List<Object> oldValue, List<Object> newValue) { 
    if (this.someList == oldValue) {
        // someList could be changed by another thread after that compare,
        // and before this set
        this.someList = newValue;
        return true;
    }
    return false;
}
    
java.util.concurrent.atomic
有时被忽视的包装描述阐述了一些常见的用途。 附录:类似地,
java.util.concurrent
的包描述方便地总结了JLS§17中详述的几个要点。 另外,如果你的
List
是不可变的,可以考虑最终字段语义学的潜在好处,并且可以对它进行引用
final
。     
  这是否意味着设置引用本身并不是原子操作? 设置引用变量是原子的,但原子操作不一定是线程安全的。让我解释。 原子意味着任何观察者(线程)都会看到变量的旧值或新值,而不是其他东西。这并不意味着所有观察者在查看变量时都会看到新值。 (正如@Tom指出的那样,引用变量的原子性没有说明它引用的对象的原子性属性。) 为了让所有观察者都能看到变量中的新值,需要进行一些同步。要更新变量,将在以下情况下执行以下操作: 变量声明为
volatile
,或 对变量的访问/更新由同一原始监视器锁同步。 包含在相关“AtomicXxx”类中的变量也将是线程安全的,但如果您想要避免锁定并且想要执行诸如原子“比较和替换”之类的操作,则通常使用这些类中的一个。 但同样,这仅适用于对象引用的线程安全性。如果对象的状态也未正确同步,则线程可以很好地看到对象属性的陈旧值等等。     
如果您不使用AtomicReference或volatile关键字并且读取引用的线程不是写入它的线程,则无法保证读取线程将看到更新的值。 在多处理器环境中尤其如此。 volatile关键字和AtomicReference(在内部使用volatile进行基本的set / get操作)强制执行内存屏障和缓存刷新,确保更新的值在主内存中可见。     
至于C#,我自己找到了答案。根据C#语言规范的第5.5节设置引用是Atomic操作。 “读取和写入以下数据类型是原子的:bool,char,byte,sbyte,short,ushort,uint,int,float和reference types。此外,读取和写入具有基础类型的枚举类型list也是原子的。其他类型的读写,包括long,ulong,double和decimal,以及用户定义的类型,都不能保证是原子的。除了为此目的设计的库函数,没有保证原子读 - 修改 - 写,例如在递增或递减的情况下。“     

要回复问题请先登录注册