【问题标题】:cout in multithread WITHOUT LOCK in C++20多线程中的 cout 没有 C++20 中的 LOCK
【发布时间】:2021-05-26 00:36:57
【问题描述】:

我正在用 C++20 编写。这是一个非常简单的程序,它要求三个线程打印一些字符串。例如,我们要求线程 1 打印 "This is thread1",线程 2 打印 "This is thread2",线程 3 打印 "This is thread3"

但是,我注意到在传递给线程的printThread 函数中,如果我们不使用锁,我们可以获得混合在线程之间的打印结果。如This is This thread2 is thread3。我想避免这样的干预,所以我用mutex写了我的代码:

#include <iostream>
#include <string.h>
#include <thread>
#include <mutex>
using namespace std;


mutex m_screen;
void printCnt()
{   
    lock_guard guard(m_screen);
    cout << "Func Start" << endl;
    // Fetch the thread ID of the thread which is executing this function
    thread::id threadID = this_thread::get_id();
    
    cout << "Thread [" << threadID << "] has been called " endl;
    
    
}

// g++ foo.cpp =pthread

int main(){
    thread t1(printCnt);
    thread t2(printCnt);
    thread t3(printCnt);

    t1.join();
    t2.join();
    t3.join();

    cout << "done" << endl;
    
}

不知道有没有什么方法可以达到和互斥锁一样的效果,但是没有锁

【问题讨论】:

  • std::osyncstream?当它刷新到 std::cout 时,它可能会在内部使用锁定,但这仍然比在流式传输期间锁定更好。
  • std::osyncstream 仍将使用某种形式的锁。
  • 您可以构造要输出的整个字符串,然后将其传递给cout。这将有一个函数调用(而不是四个)。
  • 您也许可以通过某种方式使用原子库。

标签: c++ multithreading c++11 c++20


【解决方案1】:

总的来说,这篇文章总结了 cmets 中的想法(带有示例),并添加了 1 个新方法

正如 Dean Johnson 在 cmets 中提到的,执行此操作的标准方法是 std::osyncstream 函数,然后您的代码将如下所示

void printCnt()
{   
    cout << "Func Start" << endl;
    // Fetch the thread ID of the thread which is executing this function
    thread::id threadID = this_thread::get_id();
    
    osyncstream(cout) << "Thread [" << threadID << "] has been called " endl;   
}

您也可以首先生成一个包含您的输出的字符串(正如 1201ProgramAlarm 所提到的),然后一次输出整个字符串。这可以使用std::stringstreamstd::format 来实现。结果,代码看起来像这样

void printCnt()
{   
    cout << "Func Start" << endl;
    // Fetch the thread ID of the thread which is executing this function
    thread::id threadID = this_thread::get_id();
    
    // stringstream ss;
    // ss << "Thread [" << threadID << "] has been called\n";
    // string output = ss.str(); 

    string output = format("Thread [{}] has been called\n", "world");//or use commented variant above

    cout << output;   
}

如果允许你使用 C 风格的函数,你可能想要使用 printf(通常是格式化程序 + 打印机,但据我所知 doesn't know how to print std::thread::id

void printCnt()
{   
    cout << "Func Start" << endl;
    
    static int x = 0;
    x++;
    
    printf("Thread [%d] has been called\n", x); 
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 2020-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多