cpp规范中有关mutex try_lock的错误?

时间:2015-01-17 22:40:52

标签: c++

在关注链接(http://www.cplusplus.com/reference/mutex/mutex/try_lock/)上,我们声明样本只能返回1到100000之间的值。是否声明0不能输出?

// mutex::try_lock example
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutex

volatile int counter (0); // non-atomic counter
std::mutex mtx;           // locks access to counter

void attempt_10k_increases () {
  for (int i=0; i<10000; ++i) {
    if (mtx.try_lock()) {   // only increase if currently not locked:
      ++counter;
      mtx.unlock();
    }
  }
}

int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(attempt_10k_increases);

  for (auto& th : threads) th.join();
  std::cout << counter << " successful increases of the counter.\n";

  return 0;
}

在任何情况下,很容易回答'如何获得2?',但真的不清楚如何获得1而永远不会得到0。

当没有其他线程在互斥锁上有锁时,try_lock可以“虚假失败,但在这些情况下重复调用在某些时候会成功”,但如果是,则样本可以返回0(并且也可以返回1)某些情况)。

但是,如果此规范示例声明为true且0不能输出,那么关于“虚假失败”的单词可能不是真的那么?

3 个答案:

答案 0 :(得分:2)

标准说明如下:

30.4.1.2/14 [thread.mutex.requirements.mutex]

  

实施   即使它没有被任何其他线程持有,也可能无法获得锁定。 [注意:这种虚假的失败是   通常不常见,但允许基于简单比较和交换的有趣实现   (第29条)。 - 后注]

如果所有0都失败,您甚至可以获得try_lock

另外,请不要使用cplusplus.com,它有long history有很多错误。
使用cppreference.com比标准much closer更安全。

答案 1 :(得分:1)

例如,如果另一个线程持有锁并且刚刚释放它,那么

try_lock可能会失败。你读到了这些情况&#34;在这些情况下重复的电话会在某些时候成功#34;对try_lock进行10,000次调用将计为&#34;重复调用&#34;其中一个会成功。

答案 2 :(得分:-1)

你永远不会得到0:

当第一次调用try_lock()时(首先是哪个线程无关紧要),互斥锁将被解锁。这意味着10个线程中的1个将设法锁定互斥锁,这意味着try_lock()将成功。

你可以获得1:

  • 让我们说线程0设法锁定互斥锁:

void attempt_10k_increases () { for (int i=0; i<10000; ++i) { if (mtx.try_lock()) { // thread 1 to 9 are here ++counter; // thread 0 is here mtx.unlock(); } } }

  • 现在我们说操作系统调度程序选择不运行线程0一段时间。在此期间,线程1到9继续运行,调用try_lock()并失败,因为线程0保存互斥锁。

    • 现在完成了线程1到9。他们甚至没有获得互斥锁。
    • 线程0被重新安排。它解锁互斥锁并完成。
    • 计数器现在是1.