G ++ CAS(__sync_val_compare_and_swap)问题需要解释

Sca*_*ark 6 c++ multithreading

这是我的头脑.

我正在尝试实现一些"无锁"代码并使用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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

好吧,如果我在10个并发线程中运行上面的代码,一切都很好.

但是,如果我将代码更改为read

        // acquire a lock
        while( __sync_val_compare_and_swap( &lock, lock, true ) == true )
Run Code Online (Sandbox Code Playgroud)

请注意,我已将"false"更改为"lock".

一切都破裂了,断言了

        // make sure we have the lock
        assert( lock == true );
Run Code Online (Sandbox Code Playgroud)

火灾.任何人都可以解释为什么这会有所作为?

谢谢马克.

Aid*_*lly 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.您不希望编译器优化对此类变量的引用.