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

时间:2013-09-17 07:52:43

标签: c++ multithreading concurrency

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

假设有一组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
}

3 个答案:

答案 0 :(得分:9)

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

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

答案 1 :(得分:5)

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

答案 2 :(得分:5)

Pre C ++ 11,它取决于实现;最后一个 实现保证了呼叫的同步。 (VC ++ 保证std::cout的同步,但不保证同步 iostream对象。 g ++提供与C ++ 11相同的保证, 甚至在早期版本的编译器中。)在C ++ 11中,它是 显式未定义的行为。

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

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

编辑:

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

我的全球推荐。我想不出任何现实的 不会创建字符交错的情况 一个问题。 (另外,我不认为我曾编写过代码 实际上来自std::cin的输入;它始终来自一个 std::istream&可能是std::cin,也可能是{{1}} 一个文件。)