scanf(), std::cin 在多线程环境中的行为如何

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

本文关键字:环境 std scanf cin 多线程      更新时间:2023-10-16

我想用一个例子来说明我的问题。

假设有一个设置为运行此函数的 N /*(N>>1)*/ 线程数组:

void Process() {
    //Some thread safe processing which requires in-deterministic computation time
    unsigned char byte;
    std::cin >> byte;
}

一旦它们同时启动,会发生什么?如何处理并发 std::cin 访问?在控制台上操作的最终用户看到/体验到什么?

编辑:我还想补充一件事。下面的代码是否足够安全,可以放弃仅在一个(可能是主)线程中使用 std:cin 的想法?

void Process() {
    //Some thread safe processing which requires in-deterministic computation time
    //Mutex lock
    unsigned char byte;
    std::cin >> byte;
    //Mutex unlock
}
我想

说,如果没有互斥体,结果是不可预测的。

如果使用互斥锁,一切都很好。这就是互斥锁的用途。

在 C++11 之前,这取决于实现;至少一个实现保证了调用的同步。 (VC++保证std::cout的同步,但不能保证其他IO流对象。 G++ 提供与 C++11 相同的保证,即使在早期版本的编译器中也是如此。在C++11中,它是显式未定义的行为。

一般规则很简单:对状态的任何修改任何线程中的对象都需要同步所有访问。并且std::istream上的所有>>运算符都被视为修改其状态。

更一般地说,对于任何特定的流,它可能是一个很好的仅在一个线程中使用它的策略。 (也有例外,例如日志记录流,其中日志记录对象确保线程安全。 对于输入尤其如此,因为即使外部同步,操作者的顺序将如果它们位于单独的线程中,则通常未指定。 所以即使使用同步,如果您的用户输入 "ab" ,线程得到'a',在你的例子中得到'b'将是待定。

编辑:

标准流对象似乎有特殊规则(std::cinstd::cout等)。 并发访问是保证不会产生数据竞争,至少在某些情况下是这样。它仍然可能导致字符混合,即:如果你是输入int(而不是单个字符)和您的用户输入 "123 89n" ,线程 1 可能会看到 "1389n" 和线程 2 "2 ",这不会给你连贯结果。

我的全球建议成立。 我想不出任何现实的字符交错不会创建的情况一个问题。 (另外,我认为我从来没有写过这样的代码实际来自std::cin的输入;它总是来自 std::istream&可能是std::cin的,也可能是一个文件。

第一个线程使用 std::cin 锁定它(除非您use sync_with_stdio(false))。因此,您不需要互斥锁。http://en.cppreference.com/w/cpp/io/cin无论如何,我不建议在多线程应用程序中使用它。问题是没有办法中断来自其他线程的 cin 输入。