我正在学习C ++ 11中的多线程,我尝试了这个简单的测试,但输出并不是我的预期。
#include <thread>
#include <iostream>
#include <mutex>
int main() {
auto function = [](int x) {
std::mutex m;
m.try_lock();
std::cout << "Hello" << x << std::endl;
m.unlock();
return;
};
std::thread t1(function , 1);
std::thread t2(function, 2);
std::thread t3(function, 3);
std::thread t4(function, 4);
t1.join();
t2.join();
t3.join();
t4.join();
std::cin.get();
return 0;
}
我希望输出为:
Hello1
Hello2
Hello3
Hello4
(可能不是按顺序排列,但每个hello和数字在一个单独的行中)
相反,我得到了这样的东西:
HelloHello21
Hello3
Hello4
或者
HelloHello2
1
Hello3
Hello4
除了互斥锁之外没有正确锁定的谜题是它总是将Hello1切成两半。
编辑:在VS2015中完成,如果它有任何区别(不应该因为它都是标准的吗?)
答案 0 :(得分:3)
您需要使用static
,因为所有线程都必须访问相同的互斥对象。此外,如果在您到达try_lock()
之前抛出异常,lock()
(或unlock()
)会导致问题。 std::lock_guard<>()
是一种更安全的方法,建议使用它,因为它会在你超出其范围时释放,无论是通过函数返回还是通过异常。
尝试以下功能修订版:
auto function = [](int x) {
static std::mutex m;
std::lock_guard<std::mutex> mylock(m);
std::cout << "Hello" << x << std::endl;
return;
};
有关详情,请参阅http://en.cppreference.com/w/cpp/thread/lock_guard。
另外,如果您认为将来可能会更改互斥锁类型(或者只是想尝试一下),您可以使用推断的模板类型设置互斥锁:
std::lock_guard<decltype(m)> mylock(m);
答案 1 :(得分:2)
try_lock()
并不一定会锁定互斥锁。它可能会锁定互斥锁,也可能不会。它只会尝试锁定互斥锁。如果它已经被锁定,它不会等到互斥锁被解锁,但会返回指示已经发生这种情况。
因此,实际上,您的代码最终无法以任何方式,形状,内容或形式有效地同步其输出。
如果您确实要锁定互斥锁,请使用lock()
代替try_lock()
。
编辑:正如其他人所指出的,您的代码有效地为每个线程创建了一个单独的互斥锁,因此您还需要创建该互斥锁static
。