简体   繁体   中英

std::mutex not locking properly for std::cout

I'm learning about multithreading in C++11 and I tried this simple test but the output is not what I expected.

#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;
}

I expected the output to be:

Hello1
Hello2
Hello3
Hello4

(maybe not in that order but each hello and number in a separate line)

Instead I got something like this:

HelloHello21
Hello3
Hello4

Or

HelloHello2
1
Hello3
Hello4

What puzzles besides the mutex aparently not locking properly is that it's always the Hello1 the one that gets cut in half.

EDIT: done in VS2015 if it makes any difference (should not because it's all standard?)

You need to use static , as all threads must access the same mutex object. Also, try_lock() (or lock() ) causes problems if an exception is thrown before you get to unlock() . std::lock_guard<>() is a much safer way of doing this and is recommended, as it will be released when you go out of its scope, whether it's through a function return or through an exception.

Try the following revision of the function:

auto function = [](int x) {
    static std::mutex m;
    std::lock_guard<std::mutex> mylock(m);
    std::cout << "Hello" << x << std::endl;
    return;
};

See http://en.cppreference.com/w/cpp/thread/lock_guard for more.

Also, if you think you may change the mutex type in the future (or are just trying to be fancy) you can set up the mutex with an inferred template type:

std::lock_guard<decltype(m)> mylock(m);

try_lock() does not necessarily lock the mutex. It might lock the mutex, it might not. It only tries to lock the mutex if it can. If it's already locked, it does not wait until the mutex gets unlocked, but returns an indication that this has happened.

So, in effect, your code does not end up effectively synchronizing its output, in any way, shape, matter, or form.

If you really want to lock the mutex, use lock() instead of try_lock() .

EDIT: and as someone else pointed out, your code effectively creates a separate mutex for each thread, so you need to make that mutex static , as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM