2010-01-26 281 views
6

这是做我的头。G ++ CAS(__sync_val_compare_and_swap)的问题需要解释

我试图执行一些“无锁”的代码,并正在使用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) 

通知我变“假”,以“锁定”。

所有的地狱破散,并断言

 // make sure we have the lock 
     assert(lock == true); 

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

Thx Mark。

回答

5

它在我看来就像__sync_val_compare_and_swap将始终返回变量的旧值,即使没有交换发生。在这种情况下,假设另一个线程在您尝试获取它之前就保持锁定 - 然后lock为true,并且您打电话__sync_val_compare_and_swap(&lock, true, true);。就在实际的原子比较和交换之前(但在函数参数确定之后),另一个线程释放锁 - lock变为false。 compare_and_swap然后将返回false,但不会执行swap操作,因为它所比较的​​值不是锁中的值。此线程没有执行交换,因此lock的值仍然为false,从而触发了您的断言。

顺便提一句,我强烈建议您制作lock a volatile bool。您不希望编译器优化对这些变量的引用。

+0

谢谢艾丹。我认为你已经清除它在我的脑海中。这很有趣,我如此接近代码,我甚至无法想象。这是一些生产代码中的一个错误,我直觉上认为这是错误的,但是我不能为了我的生活而头脑清醒地理解为什么。 – ScaryAardvark 2010-01-26 16:38:37

+0

是的,你是对的..我们的产品代码确实有它作为一个易变的,我的快速测试代码没有。我会相应地修改我的问题:) – ScaryAardvark 2010-01-26 16:41:08

+0

更好的可能是'volatile sig_atomic_t'。 – 2010-01-26 16:43:27