【发布时间】:2018-04-23 17:08:58
【问题描述】:
我在一个程序中尝试了 mutex::try_lock() 成员,它执行以下操作:
1) 它故意将互斥锁锁定在并行线程中。
2) 在主线程中,它尝试使用 try_lock() 锁定互斥锁。
a) 如果没有获得锁,它会将字符添加到字符串中。
b) 获取锁后,打印字符串。
我已经在 2 个在线编译器上测试了这个程序:
1) 在 coliru(其 thread::hardware_concurrency() 为 1)上,程序为 here:
int main()
{
/// Lock the mutex for 1 nanosecond.
thread t {lock_mutex};
job();
t.join();
}
/// Lock the mutex for 1 nanosecond.
void lock_mutex()
{
m.lock();
this_thread::sleep_for(nanoseconds {1});
m.unlock();
}
void job()
{
cout << "starting job ..." << endl;
int lock_attempts {};
/// Try to lock the mutex.
while (!m.try_lock())
{
++lock_attempts;
/// Lock not acquired.
/// Append characters to the string.
append();
}
/// Unlock the mutex.
m.unlock();
cout << "lock attempts = " << lock_attempts
<< endl;
/// Lock acquired.
/// Print the string.
print();
}
/// Append characters to the string
void append()
{
static int count = 0;
s.push_back('a');
/// For every 5 characters appended,
/// append a space.
if (++count == 5)
{
count = 0;
s.push_back(' ');
}
}
/// Print the string.
void print()
{
cout << s << endl;
}
这里,程序输出如预期:
starting job ...
lock attempts = 2444
aaaaa aaaaa aaaaa ...
但是,在这里,如果我从程序中删除以下语句:
cout << "starting job ..." << endl;
输出显示:
lock attempts = 0
为什么会这样?
2) 另一方面,当我在 ideone 上尝试这个程序(甚至锁定 1 秒而不是 1 纳秒)时 - here - 我总是得到一个输出显示:
lock attempts = 0
即使程序中存在诊断“启动作业”,也会发生这种情况。
ideone 的 thread::hardware_concurrency() 为 8。
也就是说,我立即成功获得了锁。为什么会这样?
请注意,这不是 try_lock() 虚假失败的情况。在这种情况下,虽然在互斥体上没有个现有锁,但成员返回 false,表示锁定尝试不成功。
在这里,相反的情况似乎正在发生。尽管互斥体上存在锁(显然),但成员返回 true,表示已成功获取新锁!为什么?
【问题讨论】:
-
您的代码中没有任何内容可以保证生成的线程将在
job开始执行之前运行。所以这可能会发生(有些时候,大多数时候,总是,没人能猜到)。 -
"但是,如果我删除" 好吧,这表明已经发生了什么:使用该语句,您的主线程在获取锁方面比其他线程慢,没有它会更快...如果您只想尝试功能,请执行以下操作:让创建的线程锁定 2 秒,并让主线程在线程创建后休眠 1 秒。然后你观察到的行为仍然发生的概率变得如此接近于你可以忽略它......
标签: c++ multithreading