【问题标题】:Why does Interlocked.Exchange not support Boolean type?为什么 Interlocked.Exchange 不支持布尔类型?
【发布时间】:2011-05-28 22:34:49
【问题描述】:

.NET 团队决定在 Interlocked.Exchange 操作中不支持布尔值有什么实际原因吗?

其中一个使用示例是当您想要保证某些代码只执行一次并且您想要为此使用布尔标志时。

【问题讨论】:

  • 您当然可以只使用intif(Interlocked.CompareExchange(ref value, 1, 0)==0) {...} - 当然不能回答为什么...或者更简单 - Lazy<T>: @ 987654321@
  • 问得好,这些年来已经多次向微软报告过这个问题。除了疏忽之外,我自己还没有看到令人满意的理由。如果有人知道,请告诉我们!
  • 如果您需要对布尔值的联锁支持,您可以使用我的 InterlockedBoolean.cs 实现

标签: c# .net multithreading


【解决方案1】:

是的,这是有充分理由的。 Interlocked 方法的实现需要处理器级别的低级支持。例如,请参阅this answer。当您定义与架构无关的框架时,这是一个问题。

在仅占本机处理器字长一小部分的数据类型上实施 Interlocked 类支持的低锁定技术是很困难的。 10 多年前流行的 RISC 设计 CPU 方法强烈反对它。操作数大小和本机内存总线宽度之间的不匹配使得它很难实现。原因之一是英特尔的 x86 架构仍然在您的膝上,因为不走捷径,它已经存在了 30 年。在wikipedia article 了解更多有关 RISC 的背景信息。

【讨论】:

  • IOW, InterlockedExchange 不存在小于 32 位的任何类型,并且缺少 bool 重载只是此的结果。
  • @Dennis:不正确。一个布尔值只有 1 个字节。在许多情况下,它将与本机系统的单词保持一致。它仍然只有 1 个字节,但您可以在 x86 系统上获得 3 个字节的填充。
  • 模拟子词 CompareExchange 似乎并不难。只需阅读整个单词,检查感兴趣的部分是否不匹配(如果是则退出),否则找出它的新值,比较它,并根据需要循环,直到 CompareExchange 成功或感兴趣的部分显示不匹配。
  • @supercat 这听起来不是很原子或无锁。
  • 您不能只读取 1 字节变量的“整个单词”。没有对齐保证,当字节是页面中的最后一个字节时,您迟早会触发 AccessViolationException。
【解决方案2】:

不回答问题,但作为一种解决方法,您可以像 C 那样使用 int 而不是 bool。

    int m_IsFirstTime = 1; // 1 means true 0 means false. 

    void SomeMethod()
    {
        if (1 == Interlocked.Exchange(ref m_IsFirstTime , 0))
            // Do something for the first time.

        else
            // Do something for all other times.

    }

附:如果有证据表明读比写快,那么 Interlocked.CompareExchange 可能更适合这种情况(只有第一次,我假设很多非第一次)。

【讨论】:

    【解决方案3】:

    如果您需要一个简单的解决方案,您可以使用对象字段来设置/获取布尔值。

        private object _isRemoved;
        public bool isRemoved
        {
            get
            {
                object returnVal = Interlocked.CompareExchange(ref _isRemoved, false, null);
                return returnVal != null && (bool)returnVal;
            }
            set
            {
                Interlocked.Exchange(ref _isRemoved, value);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2015-01-23
      • 1970-01-01
      • 2021-07-06
      • 1970-01-01
      • 2018-04-02
      • 1970-01-01
      • 2011-01-24
      • 2012-02-01
      相关资源
      最近更新 更多