std :: mutex没有正确锁定std :: cout

时间:2016-04-07 03:06:17

标签: c++ multithreading c++11

我正在学习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中完成,如果它有任何区别(不应该因为它都是标准的吗?)

2 个答案:

答案 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