printf调用乱搞std :: thread但是std :: cout很好

时间:2016-08-23 03:49:50

标签: c++ multithreading c++11

当使用printf(stdio.h)时,"启动两个线程\ n"和"输入一个数字\ n"混合在一起(类似于" StEanterrt b oththureaber \ nads \ n"),但这不会发生在std :: cout(iostream)中。我怀疑这与std :: thread有关,但我仍然是多线程编程的新手。

我真的不想使用iostream,因为它会让程序变得超大!

我正在使用mingw32 g ++ 4.9.2,使用g++ -o foreback foreback.cpp -O2 -std=c++11进行编译。 (虽然我的计算机是64位,但我发现mingw-w64通过mingw32生成的程序大小只有两倍,所以我没有使用它。)

//#define IOS
#ifdef IOS
#include <iostream>
#endif
#include <stdio.h>
#include <thread>
#include <atomic>
#include <windows.h> // for Sleep()

std::atomic<int> atom(1);

void foreground() {
    int c = 1;
    while (c) {
#ifdef IOS
        std::cout << "Enter a number: ";
        std::cin >> c;
#else
        printf("Enter a number: ");
        scanf("%d", &c);
#endif
        atom.store(c, std::memory_order_relaxed);
    }
}

void background() {
    FILE *out = fopen("foreback.txt", "w");
    int c = 1;
    while (c) {
        fprintf(out, "%d", c);
        c = atom.load(std::memory_order_relaxed);
        Sleep(500);
    }
    fclose(out);
}

int main() {
    std::thread f(foreground), b(background);
#ifdef IOS
    std::cout << "Start both threads.\n";
#else
    printf("Start both threads.\n");
#endif
    f.join();
    b.join();
#ifdef IOS
    std::cout << "End of both threads.\n";
#else
    printf("End of both threads.\n");
#endif
    return 0;
}

1 个答案:

答案 0 :(得分:1)

std::cout也不保证交错;在C ++ 03中没有提到它,而C ++ 11的FDIS在§27.4.1[iostream.objects.overview]中说明了以下内容:

  

同步访问同步(§27.5.3.4)标准iostream对象的格式化和未格式化输入(§27.7.2.1)和输出(§27.7.3.1)函数或多个线程的标准C流不得产生数据种族(§1.10)。 [注意:如果用户希望避免交错字符,则仍必须通过多个线程同步这些对象和流的并发使用。 - 结束说明]

最后的说明基本上意味着“std::cout也允许交错字符”。由于编译器/运行时库特定的实现,或者由于尝试to synchronize itself with stdio.h(关闭sync_with_stdio可能导致它再次开始交错),它可能不会这样做。但它不是语言保证;你只是幸运。

如果希望输出不交错,则需要从单个线程执行所有I / O(让工作者接受参数和计算值,主线程负责执行I / O以输出计算结果)值),或显式锁定从目标相同流/ FILE*的不同线程使用的所有I / O函数。您可以轻松使用stdio.h,只需要使用std::mutex来锁定std::lock_guard(例如stdio.h}围绕position: fixed; height: 100%; 函数的使用;只要它始终如一地完成,就可以保证不会交错。