Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
线程安全与位域 我知道BIT字段是编译器依赖的,但我没有找到最新的G++和Visual C++ 2010关于BIT字段的线程安全性的文档。_C++_C_Thread Safety_Bit Fields - Fatal编程技术网

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

线程安全与位域 我知道BIT字段是编译器依赖的,但我没有找到最新的G++和Visual C++ 2010关于BIT字段的线程安全性的文档。,c++,c,thread-safety,bit-fields,C++,C,Thread Safety,Bit Fields,位字段成员上的操作是原子的吗?如果要以线程安全的方式更新位字段,则需要将位字段拆分为单独的标志,并使用常规的ints来存储它们。访问单独的机器字是线程安全的(虽然您需要考虑多处理器系统上的优化和缓存一致性)。参见Windows 另请参见此“线程安全”在编程中是一个非常重载的术语 如果您的意思是原子访问位字段,那么答案是否定的(至少在我所知道的所有处理器上)。您可以原子访问32位机器上的32位内存位置,但这只意味着您将读取或写入整个32位值。这并不意味着另一个线程不会做同样的事情。如果您希望停止

位字段成员上的操作是原子的吗?

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

参见Windows

另请参见此

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

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

如果您的意思是同步的对位字段的访问,那么答案也是否定的,除非您将访问封装在更高级别的同步原语中(通常基于原子操作)

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

这有用吗


编辑:。

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

如果您实际上无法为所讨论的位字段使用单独的变量,则可以将多个位字段存储在一个整数中,并通过在位字段结构和32位整数之间创建并集,然后使用CompareExchange序列,以原子方式更新它们:

  • 将位字段的值读取为Int32。
  • 将其转换为位域结构
  • 更新结构
  • 将结构转换回Int32。
  • 使用CompareExchange仅当变量仍保留读入(1)的值时,才使用新值覆盖该变量;如果值已更改,请重新开始步骤(1)。 为了使这种方法很好地工作,步骤2-4必须很快。时间越长,步骤5中的CompareExchange失败的可能性就越大,因此在CompareExchange成功之前,必须重新执行步骤2-4的次数就越多。

    只需简单使用atomic.AddInt32 例如:


    atomic.AddInt32(&intval,1)“线程安全”是什么意思?@NeilButterworth:你回来了吗?我假设他在问一个位域成员上的操作是否是原子的。我的意思是,不同的线程可以访问或分配不同的成员,而不受干扰。@the_-drow:没错,我会更正这个问题。然后你在寻找对位域的原子读/写。如果你想要严格的排序读写需要同步访问位字段。听起来你可能需要两者。你是说机器字的访问是原子操作吗?GO不是C++。为了这个有用的答案,你必须用C++解释。如果位已经被设置,加法就不工作了。你必须先测试是否设置了位。
    
    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