【问题标题】:Is it thread safe to modify a nullable DateTimeOffset field without synchronization在不同步的情况下修改可为空的 DateTimeOffset 字段是否是线程安全的
【发布时间】:2018-03-21 12:33:51
【问题描述】:

给出以下课程:

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;
    }
}

根据SO answer,这里的引用分配不是线程安全的,因为When 支持字段是struct

忽略var copy = When 可能会读取 CPU 缓存并丢失最新值的可能性,是否有可能使此类代码无锁和线程安全?

【问题讨论】:

  • “是否有可能使这样的代码无锁和线程安全?”它的哪一部分?整个Work 方法?还是自己做作业?
  • 能够读取/写入何时(可为空的 DateTimeOffset)
  • 我不认为你可以。只需使用 lock 并完成它。
  • 它是一个结构,不仅仅是因为它是DateTimeOffset,还因为它可以为空。结构的更新永远不是原子的。或者换句话说,处理器必须使用多次写入来更新值。这绝不是线程安全的,另一个线程可能会在仅部分更新时观察该值。产生“撕裂的阅读”。非常讨厌的错误进行故障排除,它几乎不会经常出错。您无法调试每月仅出现一次的错误。
  • 真的这么长吗?并且不可能使用 Ticks。好的,所以这根本不可能。谢谢。

标签: c# multithreading thread-safety


【解决方案1】:

对 DateTime 的分配永远不是线程安全的(即使它为 null)。

您可以在 Int64 中使用 Ticks 而不是 DateTime,并使用 Interlocked 方法来访问它。

但是使用锁有什么问题呢?

【讨论】:

  • 锁会引入争用,因为我很想知道是否有“无锁”的方法。我想到了 Interlocked 虽然它仍然不能为空,因为它与 OP 有同样的问题
  • @BrunoGarcia 是学术兴趣还是你有 RL 用例?
  • 因为使用 Ticks(不可以为空)是最接近的答案。考虑到答案是:不可能。我会接受这个作为答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 2020-09-23
相关资源
最近更新 更多