首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#对象类型-赋值的原子性

C#对象类型-赋值的原子性
EN

Stack Overflow用户
提问于 2013-08-23 06:32:52
回答 3查看 619关注 0票数 3

快速问答。在赋值原子下面:

代码语言:javascript
复制
object [] table = new object[10]
...
table[3] = 10; //is it atomic ?
...
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-23 08:15:30

我假设OP在谈论原子性时意味着‘线程安全’。

只有当另一个线程可以读取部分写入值时,写操作才不是原子操作。

如果object [] table是方法的本地对象,那么每个线程都会得到自己的表,因此表上的任何操作都是原子的。

接下来,我假设table是跨线程共享的。

OP将表定义为object的数组。因此,table[3] = 10涉及装箱。

尽管table[3] = 10表示一个指令链,但这个操作是原子的,因为它最终将写入盒式实例的“地址”(当前的CLR实现确实表示使用内存地址的对象引用),并且地址具有机器的自然字长(即32位机器上的32位和64位机器上的64位)。请注意,即使上面的解释是基于当前的CLR实现,原子性的参考写作是保证的规格。装箱操作和装箱实例本身都是线程的本地操作,因此其他线程不可能对此进行干预。根据同样的推理,即使正在编写的值超过单词大小(例如Decimal),操作也应该是原子的(由于装箱)。这里必须注意的是,只有在已以线程安全的方式获得正在写入的值时,上述参数才有效。

如果不涉及装箱,那么word size的通常规则是原子保存(或由于内存对齐而小于单词大小)。

票数 3
EN

Stack Overflow用户

发布于 2013-08-23 06:35:37

是的,赋值是原子的,因为对象是引用类型。

正如下面所提到的,来自MSDN写的引用是原子的,对于大多数(不是所有) buil-in值类型(下面提到)和引用类型。CLI保证读取和写入值类型的变量(即处理器的自然指针大小的大小(或更小))是原子的;如果您在64位操作系统上运行C#代码,则在64位版本的CLR中读写64位双倍和长整数也保证是原子的。C#语言并不保证这一点,但运行时规范保证了这一点。

MSDN怎么说

以下数据类型的读和写都是原子的: bool、char、字节、s字节、short、ushort、uint、int、float和reference类型。此外,前面列表中具有基础类型的枚举类型的读和写也是原子的。其他类型的读和写,包括long、ulong、double和十进制,以及用户定义的类型,都不能保证是原子的。除了为此目的设计的库函数之外,没有任何原子读-修改-写入的保证,例如在增量或减少的情况下。

一个非常详细的答案,除了埃里克自己,可以看到here

票数 5
EN

Stack Overflow用户

发布于 2013-08-23 06:54:43

我严重怀疑整个术语table[3] = 10;是原子的。虽然对某些数据类型的单个读或写是原子数组访问,但很可能不是。

您的示例的IL代码是

代码语言:javascript
复制
IL_0001:  ldc.i4.s    0A 
IL_0003:  newarr      System.Object
IL_0008:  stloc.0     // table
IL_0009:  ldloc.0     // table
IL_000A:  ldc.i4.3    
IL_000B:  ldc.i4.s    0A 
IL_000D:  box         System.Int32
IL_0012:  stelem.ref

您可以看到索引是在IL_000A加载的,然后在IL_000D处对int进行装箱,最后将装箱值存储在IL_0012。

这些指令的每个独立部分可能是原子的,但这并不意味着构成table[3] = 10;的指令链是原子的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18396303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档