7

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

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

3 回答 3

9

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

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

于 2013-09-17T08:04:17.097 回答
6

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

一般规则很简单:任何线程中对象状态的任何修改都需要同步所有访问。并且所有>>操作符std::istream都被认为修改了它的状态。

更一般地说,对于任何特定的流,只在一个线程中使用它可能是一个好策略。(也有例外,例如日志流,其中日志对象确保线程安全。)对于输入尤其如此,因为即使在外部同步时,如果运算符位于单独的线程中,它们的顺序通常也不会指定。因此,即使使用同步,如果您的用户输入"ab",在您的示例中哪个线程获取'a'以及哪个获取'b'将是未确定的。

编辑:

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

我的全球建议是有效的。我想不出任何现实的情况,其中字符的交错不会造成问题。(另外,我认为我从未编写过实际输入的代码std::cin;它总是来自 std::istream&可能是std::cin,或者可能是文件的代码。)

于 2013-09-17T08:26:57.930 回答
5

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

于 2013-09-17T08:13:56.490 回答