【问题标题】:C++ threads why the cout statements are not getting printed even after fflushC++ 线程为什么即使在 fflush 之后也没有打印 cout 语句
【发布时间】:2021-01-04 13:00:27
【问题描述】:

我有一个示例代码:

#include <iostream>       // std::cout
#include <thread>         // std::thread
void pause_thread(int n)
{
    if(n != 4)
    {
        std::this_thread::sleep_for(std::chrono::seconds(100));
        std::cout << "pause of " << 100 << " seconds ended\n";
    }
    std::cout << "Thread number " << n << " ended\n";
}

int main()
{
    std::thread threads[6];                         // default-constructed threads
    std::setvbuf(stdout, NULL, _IONBF, 0);
    std::cout << "Spawning 5 threads...\n";
    for(int i = 0; i < 5; ++i)
    {
        //If the object is currently not joinable, it acquires the thread of execution represented by rhs (if any).
        //If it is joinable, terminate() is called. If it is joinable, terminate() is called.
        //rhs no longer represents any thread of execution
        threads[i] = std::move(std::thread(pause_thread, i));    // move-assign threads
    }
    std::thread& i = threads[4];
    threads[5] = std::move(threads[4]);
    std::cout << "Done spawning threads. Now waiting for them to join:\n";
    for(int i = 0; i < 6; ++i)
    {
        if(threads[i].joinable())
        {
            std::cout << "Thread " << i << " " << threads[i].get_id() << " ID joinable" << std::endl << std::flush;
            threads[i].join();
        }
        else
        {
            std::cout << "Thread " << i << " not joinable" << std::endl << std::flush;
        }
    }

    std::cout << "All threads joined!\n";


    return 0;
}

以下是我收到的输出:

Spawning 5 threads...  
Done spawning threads. Now waiting for them to join:     
Thread 0 22476 ID joinable   
Thread number 4 ended  
.... no output for 100 seconds ..
pause of 100 seconds ended
Thread number 0 ended  
pause of 100 seconds ended 
Thread 1 28676 ID joinable    
pause of 100 seconds ended 
Thread number 2 ended       
Thread number 3 ended  
pause of 100 seconds ended   
Thread number 1 ended        
Thread 2 2336 ID joinable    
Thread 3 42236 ID joinable  
Thread 4 not joinable        
Thread 5 35940 ID joinable  
All threads joined!  

“Thread n xxxx ID joinable”语句是如何在“Thread number nended”之后打印出来的?我什至尝试使用 set std::output as non buffered 但输出相同?

【问题讨论】:

  • 您还期待什么其他输出?我没有看到你得到的问题。首先线程打印一些东西,然后当你检查它们是否可加入以及加入它们时打印一些东西
  • 你没有刷新pause_thread中的cout,所以它可以像你看到的那样被打印出来。
  • std::cout 本身不是线程安全的 afaik
  • 我期待所有“线程 n xxxx ID 可连接”都应该首先打印,如果“线程编号 n 结束”那么线程 n 变得不可连接,因此应该打印“线程 n 不可连接”因为线程 n 已经终止了
  • @idclev463035818 std::cout 本身不是线程安全的 afaik AFAIK,std::iostream 线程安全的。 SO: iostream thread safety, must cout and cerr be locked separately?

标签: c++ c++14


【解决方案1】:

“Joinable”并不意味着线程仍在执行。

你首先加入线程#0。这大约需要 100 秒。
在此期间,线程 #4 完成,因为它没有休眠,而其他线程正在休眠。
如果线程的调度碰巧不同,则任何“睡眠线程”都可能会打印它们已在此处结束的信息。

一旦线程 #0 的等待结束,您就开始加入其他线程。
其中一些在您加入之前已完成执行,而另一些尚未完成。
在这个特定的例子中,它们都没有在等待线程 #0 结束之前完成,但不能保证会发生这种情况。

并注意像这样的一行

std::cout << "Thread number " << n << " ended\n";

不是原子的,来自不同线程的字符可以交错。

【讨论】:

    【解决方案2】:

    因为可加入并不代表你的想法:https://en.cppreference.com/w/cpp/thread/thread/joinable

    所以任何启动的线程都是“可加入的”,它不需要完成运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-08
      • 2015-11-02
      • 2013-01-04
      • 1970-01-01
      • 2020-06-18
      • 2011-05-19
      • 1970-01-01
      相关资源
      最近更新 更多