【问题标题】:How Compare and Swap works比较和交换的工作原理
【发布时间】:2014-04-15 21:01:24
【问题描述】:

我读过很多帖子说比较和交换保证原子性,但是我仍然无法理解它是如何做到的。这是比较和交换的一般伪代码:

int CAS(int *ptr,int oldvalue,int newvalue)
{
   int temp = *ptr;
   if(*ptr == oldvalue)
       *ptr = newvalue
   return temp;
}

这如何保证原子性?例如,如果我使用它来实现互斥锁,

void lock(int *mutex)
{  
    while(!CAS(mutex, 0 , 1));
}

这如何防止 2 个线程同时获取互斥锁?任何指针将不胜感激。

【问题讨论】:

  • 当然:ptr, mutex, NULL...
  • 不实现自己的互斥锁更安全,而是使用系统中的一些互斥锁,例如 glibc 中的pthread_mutex_lock/_unlock(在 POSIX 中定义的接口:pubs.opengroup.org/onlinepubs/009695399/functions/…
  • 我没有实现自己的互斥锁。只是想举个例子来说明我的意思。

标签: c multithreading mutex compare-and-swap


【解决方案1】:

“通用伪代码”不是 CAS(比较和交换)实现的实际代码。特殊硬件指令用于激活 CPU 中的特殊原子硬件。例如,在 x86 中,可以使用 LOCK CMPXCHG (http://en.wikipedia.org/wiki/Compare-and-swap)。

例如,在 gcc 中,有 __sync_val_compare_and_swap() 内置 - 它实现了特定于硬件的原子 CAS。 Paul E. McKenney (Is Parallel Programming Hard, And, If So, What Can You Do About It?, 2014) 第 4.3 节“原子操作”,第 31-32 页对此操作进行了描述。

如果您想了解更多关于在原子操作之上构建更高级别的同步以及使您的系统免于自旋锁和在主动旋转时消耗 cpu 周期的信息,您可以阅读有关 Linux 中的futex 机制的内容。第一篇关于 futexes 的论文是 Futexes are tricky,作者是 Ulrich Drepper 2011;另一篇是 LWN 文章 http://lwn.net/Articles/360699/(历史上的一篇是 Fuss, Futexes and Furwocks: Fast Userland Locking in Linux, 2002)

Ulrich 描述的互斥锁只使用原子操作来实现“快速路径”(当互斥锁没有被锁定并且我们的线程是唯一想要锁定它的线程时),但是如果互斥锁被锁定,线程将进入休眠状态使用 futex(FUTEX_WAIT...) (它会使用原子操作标记 mutex 变量,以通知解锁线程“有人正在睡觉等待此 mutex”,因此解锁者将知道他必须使用 futex(FUTEX_WAKE , ...)

【讨论】:

  • 据我了解,CAS 也使用锁,但在硬件级别?所以它不是无锁的,它只是在应用程序级别无锁,而不是硬件级别?
【解决方案2】:

如何防止两个线程获取锁?好吧,一旦任何一个线程成功,*mutex 将是1,因此任何其他线程的 CAS 都会失败(因为它被调用时带有预期值0)。通过将0 存储在*mutex 中来释放锁。

请注意,这是 CAS 的一种奇怪用法,因为它本质上是要求违反 ABA 的。通常,您只需使用普通的原子交换:

while (exchange(mutex, 1) == 1) { /* spin */ }

// critical section

*mutex = 0;   // atomically

或者,如果您想稍微复杂一些并存储有关哪个线程拥有锁的信息,您可以使用 atomic-fetch-and-add 进行技巧(例如,参见 Linux 内核自旋锁代码)。

【讨论】:

    【解决方案3】:

    不能在 C 中实现 CAS。它是在汇编的硬件级别上完成的。

    【讨论】:

      猜你喜欢
      • 2021-03-09
      • 1970-01-01
      • 1970-01-01
      • 2016-01-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2010-12-03
      • 2014-09-16
      相关资源
      最近更新 更多