如何在不同步的情况下使用多个线程(2、4、8、16 个线程)循环打印字符串(10,100、1000 个循环)?

Posted

技术标签:

【中文标题】如何在不同步的情况下使用多个线程(2、4、8、16 个线程)循环打印字符串(10,100、1000 个循环)?【英文标题】:How can I print a string in a loop (10,100, 1000 cycles) using multiple threads (2, 4,8 , 16 threads) with no synchronization? 【发布时间】:2019-10-15 15:46:14 【问题描述】:

我需要编写一个将字符打印到控制台的程序。线程不需要同步,这意味着数据会混合,输出应该是混乱的。但是,我的输出工作正常,似乎我做错了什么。

typedef struct 
    std::string info;
    unsigned int m_number;
    unsigned m_cycles;
    unsigned m_currentThread;
data;

unsigned int __stdcall Func(void* d) 
    data* real = (data*)d;
    std::cout << "Current thread ID: " << GetCurrentThreadId() << std::endl;
    int i = 0;
    for (int j = (real->m_currentThread - 1) * real->m_cycles / real->m_number;j < real->m_currentThread * real->m_cycles / real->m_number;j++) 
        std::cout << real->info << std::endl;
        

    return 0;


int main(int argc, char* argv[]) 
    int threadsNumber;
    std::string str;
    std::getline(std::cin, str);
    std::cout << "Enter the number of threads:\n";
    std::cin >> threadsNumber;
    int cycles;
    std::cout << "Enter the number of cycles:\n";
    std::cin >> cycles;
    std::vector<HANDLE> threads;
    HANDLE tmp;
    data* args = new data;
    args->info = str;
    args->m_number = threadsNumber;
    args->m_cycles = cycles;
    for (int i = 1;i <= threadsNumber;++i) 
        args->m_currentThread = i;
        tmp = (HANDLE)_beginthreadex(0, 0, &Func, args, 0, 0);
        Sleep(1000L);
        threads.push_back(tmp);
    
    WaitForMultipleObjects(threads.size(), &threads.front(), TRUE, INFINITE);

    getchar();
    return 0;

输出应该是逐字符的,字符串应该是混乱的,因为线程之间还没有同步。

【问题讨论】:

cout 有它自己的同步。两个调用不会交错,thread1: cout &lt;&lt; "foo"; thread2: cout &lt;&lt; "bar"; 只会给你"foobar""barfoo" 无关:如果您使用的是 C++11 或更高版本,则可以使用标准的 std::thread 和朋友,而不是 Windows 特定的函数。 我的猜测是Sleep(1000L) 让您的线程在开始下一个线程之前完成执行。为什么不立即启动它们? @anastasiia_kos 您正在使用std::vector,这不是 WinAPI 函数。它是标准库中的一个类,就像std::thread 一样。只是说... @JesperJuhl - 因为线程入口点必须是__stdcall。所以你需要或设置/Gz 选项或使用显式__stdcall 【参考方案1】:

输出应该是逐字符的,字符串应该是混乱的

这没有std::cout的合约支持:

除非已发出sync_with_stdio(false),否则从多个线程同时访问这些对象以进行格式化和未格式化输出都是安全的。

观察到的行为与预期的行为相匹配。

【讨论】:

以上是关于如何在不同步的情况下使用多个线程(2、4、8、16 个线程)循环打印字符串(10,100、1000 个循环)?的主要内容,如果未能解决你的问题,请参考以下文章

OkHttp 如何在不使用线程的情况下通过看似同步的 HTTP 连接执行并行 HTTP 请求?

如何在不同步的情况下使用 Delphi (Pre Delphi 2010) 版本更新 GUI 控件

在不使用推力的情况下,每个线程具有多个元素的并行前缀总和

Qt - 如何在不显式实现线程的情况下同时运行两个插槽

如何在不引用表单的情况下使用 ISynchronizeInvoke

代码优化