【问题标题】:C++ Is Mutex the only way to lock shared resourcesC++ 是 Mutex 锁定共享资源的唯一方法
【发布时间】:2014-10-01 03:44:07
【问题描述】:

除了互斥锁,你还能用什么来锁定 C++?处理器级别有什么可以使用的吗?

【问题讨论】:

标签: c++ multithreading visual-c++ c++11


【解决方案1】:

您可以使用比较和交换,类似于:

std::atomic_bool locked = false;
bool f = false;
... // spawn threads n' stuff
do {
  bool got_lock = atomic_compare_exchange_weak(locked, &f, true);
  if (got_lock) {
     ... // do stuff
     locked = false;
  }
}
while(!got_lock)

我在概念上将变量命名为locked 和got_lock,但这里没有真正的锁定。 atomic_compare_exchange_weak 函数利用特殊的汇编指令来实现原子性。

要了解它是如何工作的:它进入 do while 循环并立即尝试 CAS。 CAS 将locked 的值与f 中包含的值进行比较,结果为假。当且仅当它们比较相等时,它将locked 设置为第三个参数(true)并返回true。否则,这意味着另一个线程已经将locked设置为true,因此它返回false并且不会更改locked的值。我们可以看到,如果一个线程获得了锁,它会进入 if,做一些事情,然后释放锁。如果它没有获得锁,它不会通过 if,但它会被 while 循环弹回。它在这个非常快的 while 循环中继续,直到 CAS 调用成功。

所以,在我写下“做事”评论的地方,您可以保证一次只能有一个线程。

【讨论】:

    【解决方案2】:

    如果您在操作系统下开发,那么您也可以使用信号量。与互斥锁相比,信号量可以用某个数字作为计数器进行初始化。您初始化信号量的值允许任何调用者获取资源或执行关键代码部分,直到值(信号量)大于零。当它倒数为零时,任何新的调用者都将等待释放/释放信号量。并且二进制信号量本身就是互斥体。

    【讨论】:

      【解决方案3】:

      操作系统原语与锁相比有一个关键优势,即使用操作系统原语会将您的线程放入内核中的等待队列中。当一个互斥锁被释放时,你的线程可以被操作系统自动唤醒并启动。如果您使用比较/交换类型检查,您有责任编写自旋锁并适当地休眠(否则当您没有锁时,您将使用 100% 的处理器(或内核)等待它释放)。

      Mutex 擅长跨进程同步(需要操作系统)。 Semaphore 非常相似,只是它允许并发访问临界区(例如,允许 4 个线程仅从工作队列运行以优化多核处理器上的工作)。

      如果您只在同一进程中同步线程,您还可以使用“CRITICAL_SECTION”MSDN LINK。这会更快,因为您不需要系统调用来实现锁定。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-17
        • 2017-01-27
        • 2022-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多