How do scanf(), std::cin behave on multithreaded environment?

孤街浪徒 提交于 2020-01-03 08:49:11

问题


I'd like to state my problem using an example.

Assuming there is an array of N /*(N>>1)*/ threads which are set to run this function:

void Process() {
    //Some thread safe processing which requires in-deterministic computation time

    unsigned char byte;
    std::cin >> byte;
}

Once all of them are started simultaneously, what does happen? How are concurrent std::cin accesses handled? What does the end-user who operates on console see/experience?

Edit: There is one more thing I'd like to add. Is the code below safe enough to abandon the idea of using std:cin only in one (probably main) thread?

void Process() {
    //Some thread safe processing which requires in-deterministic computation time

    //Mutex lock
    unsigned char byte;
    std::cin >> byte;
    //Mutex unlock
}

回答1:


Pre C++11, it depends on the implementation; at least one implementation guaranteed synchronization of the calls. (VC++ guarantees the synchronization of std::cout, but not for other iostream objects. g++ offers the same guarantees as C++11, even in earlier versions of the compiler.) In C++11, it is explicitly undefined behavior.

The general rule is simple: any modification of state of an object in any thread requires all accesses to be synchronized. And all >> operators on std::istream are considered to modify its state.

More generally, for any particular stream, it is probably a good policy to use it in only one thread. (There are exceptions, such as logging streams, where the logging object ensures thread safety.) This is especially true of input, since even when synchronized externally, the sequencing of the operators will generally be unspecified if they are in separate threads. So even with synchronization, if your user inputs "ab", which thread gets 'a' and which gets 'b' in your example would be undetermined.

EDIT:

There seem to be special rules for the standard stream objects (std::cin, std::cout, etc.). Concurrent access is guaranteed not to produce a data race, at least in some cases. It may still result in characters being mixed, i.e.: if you're inputing int (rather than a single character), and your user inputs "123 89\n", there's a possibility that thread 1 will see "1389\n", and thread 2 "2 ", which won't give you coherent results.

My global recommendation stands. I can't think of any realistic case where the interleaving of characters wouldn't create a problem. (Also, I don't think I've ever written code which actually inputs from std::cin; it's always from an std::istream& which might be std::cin, or might be a file.)




回答2:


I would say, the result is not predictable without mutexes.

If you use a mutex, everything is fine. That's what mutexes are for.




回答3:


The first thread uses std::cin locks it (Unless you use sync_with_stdio(false)). So, you don't need a mutex. http://en.cppreference.com/w/cpp/io/cin Anyway I don't recommend to use it in multi-thread application. The problem is there's no way to interrupt cin input from other thread.



来源:https://stackoverflow.com/questions/18844239/how-do-scanf-stdcin-behave-on-multithreaded-environment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!