c++ - C++11 中的基本线程锁定

标签 c++ multithreading c++11 locking

如何锁定我的线程,使我的输出不是这样的: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/

相关文章:

c++ - 同步 boost ASIO : Asynchronous write,

C++ 模板 - 广义操作和实例之间成员的可见性

c++ - C++11 中的构造

c++ - 将 tm 结构转换为 boost::local_time::local_date_time

c++ - 'int [0]' c++ 的初始值设定项太多

c++ - utfcpp 和 Win32 宽 API

multithreading - QThread 事件循环和无限工作循环

c++ - 如何取消 std::async 函数?

c++ - 声明数组并稍后赋值

iphone - 使用performSelectorInBackground运行加载指示器