【发布时间】:2017-03-07 19:12:29
【问题描述】:
我试图理解为什么我的互斥锁的行为不像我预期的那样。
我正在调试另一个问题,并决定制作一个非常简单的可执行文件来直接测试互斥体的行为。这是我想出的:
#include <mutex>
#include <thread>
#include <iostream>
#include <chrono>
int main(int argc, char** argv)
{
std::mutex myMutex;
auto threadGenerator = [&] (std::string printout)
{
auto threadFunctor = [&, printout] {
int count = 0;
while (count < 300)
{
std::lock_guard<std::mutex> lock(myMutex);
std::cout << printout << std::endl;
count++;
// Sleep ensures that the other thread will be waiting on mutex
// when I release lock
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
};
return threadFunctor;
};
auto thread1Functor = threadGenerator("Thread 1 got lock");
auto thread2Functor = threadGenerator("Thread 2 got lock");
std::thread thread1(thread1Functor);
std::thread thread2(thread2Functor);
thread1.join();
thread2.join();
return 0;
}
这只是产生了两个线程,它们重复锁定和解锁互斥体,同时打印一些输出。我添加了 sleep 来强制 lock_guard 阻塞并且线程互相等待。
这会产生以下输出:
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
Thread 1 got lock
最终,一旦线程 1 完成,线程 2 将再次开始获取锁。
他们不应该在线程 1 和线程 2 之间交替吗?锁应该在每次循环迭代结束时释放,这应该允许其他线程控制互斥锁。为什么没有发生这种情况?有什么方法可以实现吗?
【问题讨论】:
-
是的,这会解决它,但有必要这样做吗?每当您使用互斥体时,是否需要添加睡眠周期才能使其工作?
-
@user2445507 不,没有必要
-
std::mutex不保证公平。 -
显然这是用于测试概念的玩具代码,但如果您想要线程 A,然后 B 并返回 A 等......并且它们从不同时运行,您可能根本不需要线程。你想要一个状态机。
-
我想我需要一个条件变量才能真正让它按预期工作。但这无论如何都是一个人为的例子。现在我知道 mutex 并不能保证公平,所以我会为此做好计划。
标签: c++ multithreading mutex