问题:在同一 unsigned int 变量上执行按位运算(清除两个不同位位置)的两个线程正在创建竞争条件。 (它是一个标志变量)。
目前尝试解决方案:每次在设置或清除位位置之前使用互斥锁。
环境:Android用户空间,仿生,C ++
现在,我还想到检查是否可以避免使用android的原子操作函数的竞争条件,
android_atomic_and/android_atomic_or
并将变量定义为volatile unsigned int
。
根据我的理解,这在逻辑上类似于atomic_set
,atomic_and
等内核空间原子操作。
所以,如果有人能够明确我的疑问,或者有其他解决方案可以更好地解决这个问题,请提供帮助。
答案 0 :(得分:2)
对于这个问题,有许多不同的解决方案。 在大多数系统上,基本整数运算通常是原子的但是你必须确保变量没有被缓存,并且基本操作可以一步完成。因此,将整数设置为0将是这样的基本操作。但是将它的值增加一个,或者在某个地方改变一点则不是。因为你正在读取当前状态,计算新状态,最后将其写回。同时执行相同操作的另一个线程将导致状态不一致。 (作为一个例子,一个变量增加了两倍,但它的值只有一个)
一种解决方案是使用锁定来访问此整数。
另一种更快的方法是使用compare_and_set方法进行写入。 (读取应该没问题)在这种情况下,请确保您的变量没有缓存在其中一个CPU中,例如通过声明它是volatile。 这可能对你有所帮助;
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
These builtins perform an atomic compare and swap. That is, if the current value of *ptr is oldval, then write newval into *ptr.
The “bool” version returns true if the comparison is successful and newval was written. The “val” version returns the contents of *ptr before the operation.
我从这里得到这部分:http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html
使用比较和设置正确,您可以确保仅修改变量,如果没有其他人同时执行此操作。因此,您需要在while循环中使用它,如此主题中所示:How to compare and swap atomically in ARM7?
第三种方法是前往一个图书馆,为您提供许多不同的“原子操作”的长列表。这可能是最干净的方式。 使用volatile和compare-and-set进行自我处理可能很危险,因为如果在某处忘记了对变量的特殊处理,它就不会警告你或其他人。
最后一件事。请注意,未受保护的读访问仅适用于单个整数变量。如果使用double或两个整数,则可能会出现不一致的状态。在写入进程0期间,当你在线程1中读取它时,一半的双变量(或两个整数)已经具有新值而另一部分仍然是旧值。这将直接导致难以找到错误。很少发生,但灾难发生时。 (这部分仅适用于常见的32位CPU系统。某些较小的系统可能会处理较小块的内存。另一方面,64位系统通常将两个整数(64位)作为一个块处理,在那里它可以与double一起使用,但不能与更大的结构)
祝你好运!