如何锁定我的线程,使我的输出不是这样的:hello...hello...hheelhllelolo.l..o......
std::size_t const nthreads=5;
std::vector<std::thread> my_threads(nthreads);
for(unsigned i=0;i<nthreads;i++)
{
my_threads[i] = std::thread ([] () {std::cout << "hello...";});
}
最佳答案
标准说:
Concurrent access to a synchronized (27.5.3.4) standard iostream object’s formatted and unformatted input (27.7.2.1) and output (27.7.3.1) functions or a standard C stream by multiple threads shall not result in a data race (1.10). [Note: Users must still synchronize concurrent use of these objects and streams by multiple threads if they wish to avoid interleaved characters. — end note]
— [iostream.objects.overview] 27.4.1 p4
请注意,不产生数据竞争的要求仅适用于标准 iostream 对象(cout、cin、cerr、clog、wcout、wcin、wcerr 和 wclog)并且仅在它们同步时(默认情况下它们是同步的)并且可以使用 sync_with_stdio 成员函数禁用)。
不幸的是,我注意到了两种现象;实现要么提供比要求更严格的保证(例如,所有流对象的线程同步,无论如何,性能不佳)或更少(例如,sync_with_stdio 的标准流对象会产生数据竞争)。 MSVC 似乎倾向于前者,而 libc++ 倾向于 the latter。 .
无论如何,如注释所示,如果你想避免交错字符,你必须自己提供互斥。这是一种方法:
std::mutex m;
struct lockostream {
std::lock_guard<std::mutex> l;
lockostream() : l(m) {}
};
std::ostream &operator<<(std::ostream &os, lockostream const &l) {
return os;
}
std::cout << lockostream() << "Hello, World!\n";
这样就创建了一个锁守卫,并在使用 std::cout 的表达式的持续时间内存在。您可以将 lockostream 对象模板化以适用于任何 basic_*stream,甚至可以在流的地址上工作,以便每个流都有一个单独的互斥量。
当然,标准流对象是全局变量,因此您可能希望像避免所有全局变量一样避免它们。它们对于学习 C++ 和玩具程序很方便,但您可能希望为实际程序安排更好的东西。
关于c++ - C++11 中的基本线程锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12605725/