替换成员变量线程的值是否安全?

svb*_*svb 9 c# multithreading thread-safety

在我的应用程序中(用C#编写)我有一个类的实例,其中一个成员变量指向另一个类的实例.第二个实例是只读的,因此该实例的状态在创建后永远不会更改.但在某些情况下,我想用一个新的更新实例替换此实例.在多线程环境中,在第一个实例中替换此引用是否安全?或者这会导致问题吗?

Hen*_*man 9

简单的写操作本身就是线程安全的.

所以这是好的:

x.y = new Y();   // OK
Run Code Online (Sandbox Code Playgroud)

但以下不是:

if (x.y == null)
    x.y = new Y();   // might overwrite a non-null x.y
Run Code Online (Sandbox Code Playgroud)

所以这取决于你想如何使用它,以及线程的期望.但原子性意味着你永远不会有一个无效的(半写的)引用x.y

  • @Adriano:怎么会失败? (4认同)

Gaz*_*yer 6

是的,在参考读/写是原子的意义上它是"安全的".您的客户端代码将始终获得有效的实例.

显然,您不能保证客户端代码会立即获得新实例.

  • OP基本上询问是否可以使用引用赋值进行撕裂,其中引用本身指向垃圾,因为它不是原子操作.这不可能发生,因为.NET确保引用分配是原子的.OP表示他只关心变量(来自任何线程)在任何时间点都会指向一个有效的实例,即使它是一个"旧的"实例.这个答案证实了OP希望听到的内容.(1) (6认同)
  • 因为代码仍然有旧实例可能无关紧要.即使使用volatile,客户端代码也可以缓存或临时复制引用.这种线程同步超出了问题的范围. (5认同)
  • "显然你无法保证客户端代码会立即获得新实例"那么你怎么能说它是线程安全的呢?它比例外更危险! (2认同)