未加同步时修改可空DateTimeOffset字段是否线程安全?
问题解答:未添加同步机制时修改可空DateTimeOffset字段是否线程安全?
答案是:不安全。
咱们来拆解你给出的LockfreeThing类代码:
public class LockfreeThing { public DateTimeOffset? When { get; private set; } public void Work(DateTimeOffset? someOffset) { var copy = When; if (copy.HasValue) { if (copy > someOffset) { // Use copy safely } else { When = null; } } When = someOffset; } }
关键原因在于:DateTimeOffset?本质是Nullable<DateTimeOffset>结构体(值类型),而.NET中对大于32位的值类型赋值操作不是原子性的。Nullable<DateTimeOffset>包含两个成员:一个bool类型的HasValue标记,以及8字节的DateTimeOffset类型Value,整个结构体的大小超过了32位。当多个线程同时执行When = someOffset或者When = null这类赋值操作时,可能会出现“撕裂写”——也就是一个线程只完成了部分字段的写入,另一个线程就读取到了半更新的、不一致的结构体状态。
举个例子:线程A正在执行When = someOffset(设置HasValue=true和对应的Value),刚写完HasValue还没写完Value的时候,线程B读取When,就会拿到一个HasValue=true但Value是旧值(甚至是无效垃圾值)的错误状态,这会导致后续的逻辑判断完全失效。
内容的提问来源于stack exchange,提问作者Bruno Garcia
相关产品推荐
相关产品推荐

