【问题标题】:Thread safety and bit-field线程安全和位域
【发布时间】:2011-05-31 19:36:49
【问题描述】:

我知道位域依赖于编译器,但我没有找到有关最新 g++ 和 Visual C++ 2010 位域线程安全的文档。

对位域成员的操作是原子的吗?

【问题讨论】:

  • “线程安全”是什么意思?
  • @NeilButterworth:你回来了吗?我假设他在询问对位域成员的操作是否是原子的。
  • 我的意思是,不同的成员可以被不同的线程访问或分配,而不会受到干扰。 @the_drow:确切地说,我会纠正这个问题。
  • 那么您正在寻找对位域的 原子 读/写操作。如果你想要严格的读/写顺序,你需要同步访问位域。听起来你可能需要两者。

标签: c++ c thread-safety bit-fields


【解决方案1】:

不幸的是,“线程安全”在编程中是一个非常重载的术语。

如果您的意思是 原子 访问位域,答案是否定的(至少在我知道的所有处理器上)。您可以原子访问 32 位机器上的 32 位内存位置,但这仅意味着您将读取或写入整个 32 位值。这并不意味着另一个线程不会做同样的事情。如果您想停止,您可能需要同步。

如果您的意思是对位域的同步访问,答案也是否定的,除非您将访问包装在更高级别的同步原语中(通常建立在原子操作之上)。

简而言之,编译器不提供对位字段的原子同步访问,而无需您进行额外的工作。

这有帮助吗?

编辑Dr. Dan Grossman has two nice lectures on atomicity and synchronization I found on UOregon's CS department page

【讨论】:

    【解决方案2】:

    写入位域时,可能存在一个时间窗口,在此时间窗口中,另一个线程访问(读取或写入)同一结构中的任何(相同或不同)位域的任何尝试都将导致未定义的行为,意味着任何事情都可能发生。读取位域时,可能存在一个时间窗口,当另一个线程尝试在同一结构中写入任何位域时,将导致未定义行为。

    如果您实际上不能为相关位域使用单独的变量,您可以将多个位域存储在一个整数中,并通过在位域结构和 32 位结构之间创建联合来自动更新它们整数,然后使用 CompareExchange 序列:

    1. 将位域的值读取为 Int32。
    2. 将其转换为位域结构
    3. 更新结构
    4. 将结构转换回 Int32。
    5. 仅当变量仍保留在 (1) 中读取的值时,才使用 CompareExchange 用新值覆盖该变量;如果值已更改,请从步骤 (1) 重新开始。

    要使这种方法运作良好,步骤 2-4 必须快速。它们花费的时间越长,步骤 5 中的 CompareExchange 失败的可能性就越大,因此在 CompareExchange 成功之前必须重新执行步骤 2-4 的次数越多。

    【讨论】:

      【解决方案3】:

      如果您想以线程安全的方式更新位域,您需要将位域拆分为单独的标志并使用常规的ints 来存储它们。访问单独的机器字是线程安全的(尽管您需要考虑多处理器系统上的优化和缓存一致性)。

      【讨论】:

      • 你的意思是访问机器字是原子操作吗?
      【解决方案4】:

      【讨论】:

        【解决方案5】:

        只需简单地使用 atomic.AddInt32 示例:

        atomic.AddInt32(&intval, 1 << 0)      //set the first bit
        atomic.AddInt32(&intval, 1 << 1) //set the second bit
        atomic.AddInt32(&intval, -(1 << 1 + 1 << 0)) //clear the first and second bit
        

        代码在 Go 中,我认为 c++ 也有类似 atomic.AddInt32 的东西

        【讨论】:

        • Go 不是 C++。要使这成为一个有用的答案,您必须用 C++ 解释它。
        • 如果该位已设置,则添加将不起作用。您必须先测试该位是否已设置。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-09
        • 2014-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多