这是我的目标。
我正在尝试实现一些“无锁”代码并使用CAS(gcc __sync_val_compare_and_swap)来解决这个问题。
我的问题可以通过以下代码显示。
volatile bool lock;
void *locktest( void *arg )
{
for ( int i = 0 ; i < 100000 ; ++i )
{
// acquire a lock
while( __sync_val_compare_and_swap( &lock, false, true ) == true )
{
// Spin while we don't acquire
}
// make sure we have the lock
assert( lock == true );
// release the lock
assert( __sync_val_compare_and_swap( &lock, true, false ) == true );
}
}
好的,如果我在10个并发线程中运行上面的代码,一切都很好。
但是,如果我将代码更改为
// acquire a lock
while( __sync_val_compare_and_swap( &lock, lock, true ) == true )
注意我已将“false”更改为“lock”。
所有地狱都破裂了,断言
// make sure we have the lock
assert( lock == true );
触发。任何人都可以解释为什么会有所作为吗?
THX 标记
答案 0 :(得分:5)
在我看来,__sync_val_compare_and_swap
将始终返回变量的旧值,即使没有发生交换。在这种情况下,假设另一个线程在您尝试获取锁之前持有锁 - 然后lock
为真,并且您正在调用__sync_val_compare_and_swap(&lock, true, true);
。在实际的原子比较和交换之前(但在确定了函数参数之后),另一个线程释放锁 - lock
变为false。然后compare_and_swap
将返回false,但不会执行swap
操作,因为它与之比较的值不是锁中的值。此线程未执行交换,因此lock
的值仍为false
,从而触发您的断言。
顺便说一下,我强烈建议lock
为volatile bool
。您不希望编译器优化对这些变量的引用。