为什么Interlocked.Exchange不支持布尔类型?

Den*_*nis 61 .net c# multithreading

有没有一些实际的理由说明.NET团队决定在Interlocked.Exchange操作中不支持布尔值?

其中一个用法示例是,当您要保证某些代码只执行一次并且您希望使用布尔标志时.

Han*_*ant 59

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

在本机处理器字大小的一小部分的数据类型上实现Interlocked类支持的低锁技术是困难的.10年多以前流行的用于cpu设计的RISC方法强烈劝阻它.操作数大小和本机内存总线宽度之间的不匹配使得它很难实现.英特尔的x86架构仍然在你的腿上的一个原因是,已经30年没有采取捷径.有关RISC的更多背景信息,请参阅此维基百科文章.

  • IOW,对于小于32位的任何类型,"InterlockedExchange"不存在,并且缺少`bool`重载只是其结果. (20认同)
  • @Dennis:不对.bool只有1个字节.在许多情况下,它将与本机系统的单词对齐.它仍然只有1个字节,但你可以在x86系统上获得3个字节的填充. (4认同)
  • 你不能只读一个1字节变量的"整个单词".没有对齐保证,当字节是页面中的最后一个字节时,你迟早会*访问AccessViolationException. (4认同)
  • 模拟一个子字CompareExchange似乎并不难.只需阅读一个完整的单词,检查感兴趣的部分是否不匹配(如果是,则退出),否则计算其新值,CompareExchange它,并根据需要循环,直到CompareExchange成功或感兴趣的部分显示不匹配. (2认同)

ILI*_*DNO 15

没有回答这个问题,但作为一种解决方法,你可以像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.

    }
Run Code Online (Sandbox Code Playgroud)

PS如果有证据表明读取比写入更快,那么Interlocked.CompareExchange对于这种情况可能更好(只有一次第一次,我假设很多非第一次).