【发布时间】:2018-10-30 16:26:14
【问题描述】:
这段代码演示了互斥锁在两个线程之间共享,但是thread_mutex 周围的范围块发生了一些奇怪的事情。
(我在another question 中有此代码的变体,但这似乎是第二个谜。)
#include <thread>
#include <mutex>
#include <iostream>
#include <unistd.h>
int main ()
{
std::mutex m;
std::thread t ([&] ()
{
while (true)
{
{
std::lock_guard <std::mutex> thread_lock (m);
usleep (10*1000); // or whatever
}
std::cerr << "#";
std::cerr.flush ();
}
});
while (true)
{
std::lock_guard <std::mutex> main_lock (m);
std::cerr << ".";
std::cerr.flush ();
}
}
这基本上可以正常工作,但 thread_lock 周围的范围块理论上应该是不必要的。但是,如果您将其注释掉...
#include <thread>
#include <mutex>
#include <iostream>
#include <unistd.h>
int main ()
{
std::mutex m;
std::thread t ([&] ()
{
while (true)
{
// {
std::lock_guard <std::mutex> thread_lock (m);
usleep (10*1000); // or whatever
// }
std::cerr << "#";
std::cerr.flush ();
}
});
while (true)
{
std::lock_guard <std::mutex> main_lock (m);
std::cerr << ".";
std::cerr.flush ();
}
}
输出是这样的:
........########################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
也就是说,thread_lock 似乎永远不会屈服于main_lock。
如果删除了冗余范围块,为什么thread_lock 总是获得锁定而main_lock 总是等待?
【问题讨论】:
-
不能保证公平调度。这两种行为都是标准允许的。
-
不应该有一些调度的保证吗?
-
main_lock饿死了。在您的代码的未注释版本中,有一个 I/O 操作,这让您的主线程有时间获得互斥锁。互斥锁是不公平的,所以如果在移除锁和取回锁之间有很短的距离(如您的代码的第二个版本),您的线程t很有可能会首先再次锁定互斥锁。跨度> -
@spraff 保证可能很昂贵,而且它不是 C++ 方式为您提供昂贵的解决方案只是“因为”; )。
-
范围块不是“冗余的”。互斥锁被锁定到
thread_lock的范围结束,所以thread_locks 范围的结束位置很重要
标签: c++ multithreading pthreads std stdmutex