美文网首页
C++ 11多线程并发模式下实现带锁的std::cout,并发输

C++ 11多线程并发模式下实现带锁的std::cout,并发输

作者: FredricZhu | 来源:发表于2023-09-13 10:00 被阅读0次

本例本意是模拟一个简单的barrier程序。就是使用线程组的join功能实现栅栏。但是在多线程输出的过程中,因为抢占控制台输出资源,会导致每个 operator<< 后面的输出被截断。相当于每次调用operator <<,是一次没有进行同步的写控制台操作,就会乱序。

然后谷歌了一下解决方案,可以继承一个std::stringstream,在继承类的析构函数中加锁,一次性全部输出rdbuf,避免中间被截断的问题。

方案比较简单。代码如下,
conanfile.txt

[requires]
boost/1.72.0

[generators]
cmake

CMakeLists.txt

cmake_minimum_required(VERSION 3.3)


project(3_thread_barrier)

set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig/")

set ( CMAKE_CXX_FLAGS "-pthread")
set(CMAKE_CXX_STANDARD 17)
add_definitions(-g)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

include_directories(${INCLUDE_DIRS})
LINK_DIRECTORIES(${LINK_DIRS})

file( GLOB main_file_list ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) 

foreach( main_file ${main_file_list} )
    file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${main_file})
    string(REPLACE ".cpp" "" file ${filename})
    add_executable(${file}  ${main_file})
    target_link_libraries(${file} ${CONAN_LIBS} pthread)
endforeach( main_file ${main_file_list})

async_out.hpp

#ifndef _FREDRIC_ASYNC_OUT_HPP_
#define _FREDRIC_ASYNC_OUT_HPP_

#include <sstream>
#include <mutex>
#include <iostream>

struct AsyncOut: public std::stringstream {
    static inline std::mutex cout_mutex;

    ~AsyncOut() {
        std::lock_guard<std::mutex> lock(cout_mutex);
        std::cout << rdbuf();
        std::cout.flush();
    }
};

#define aout AsyncOut{}

#endif

main.cpp

#include <iostream>
#include <thread>
#include <vector>
#include <algorithm>
#include <mutex>
#include "asyc_out.hpp"

int main(int argc, char* argv[]) {
    std::vector<std::thread> workers;
    for(int i=0; i<10; ++i) {
        workers.push_back(std::thread([i](){
            aout << "Hello from thread: " << i << "!\n";
        }));
    }

    // 每次运行 Hello from main的执行时机都不一样,充满了不确定性
    // Hello from thread 还有可能被截断
    // 我们希望每次的运行结果都一样
    aout << "Hello from main!\n";
    std::for_each(workers.begin(), workers.end(), [](std::thread& th) {
        th.join();
    });
  
    return EXIT_SUCCESS;
}

注意因为本例没有用到boost和其他三方库,所以可以直接用g++编译,注意链接上thread库就可以了。不一定非要CMake和conan加持。

程序输出如下,


image.png

相关文章

  • C++并发编程实战介绍附下载

    《C++并发编程实战》是一本基于C++11新标准的并发和多线程编程深度指南。内容包括从std::thread、st...

  • 多线程方法

    一. 基础并行多线程结构 二. 标准多线程方法,控制并发线程数,带线程锁

  • Go控制程序生命周期

    近期学了go语言的并发编程,掌握了 并发原语-原子锁,互斥锁,通道 并发原理 并发设计模式今天我们就来锻炼一下,如...

  • Concurrency

    线程的产生 多线程并发高级接口std::async()和类std::future<> 1,async()使得可调用...

  • java并发

    1.并发编程中的锁 并发编程中的各种锁java高并发锁的3种实现Java并发机制及锁的实现原理 2.线程池核心线程...

  • iOS多线程随笔

    1. 多线程的并发控制 1.1 在CGD中快速实现多线程的并发控制 NSOperationQueue来处理并发控制...

  • RAC 与 多线程

    07 - RAC与多线程 RAC怎么实现多线程并发处理订阅? RAC多线程模式怎么解决资源抢夺? RAC怎么实现取...

  • 2021-01-21

    C++11std::call_once的作用是很简单的,就是保证函数或者一些代码段在并发或者多线程的情况下,始终只...

  • DCL单例模式

    DCL(Double Check Lock双端检锁机制)单例模式:适用于多线程高并发场景

  • 关于并发编程的博客收藏

    Android并发编程 开篇http://ddrv.cn/a/23502/ Android并发编程 多线程与锁ht...

网友评论

      本文标题:C++ 11多线程并发模式下实现带锁的std::cout,并发输

      本文链接:https://www.haomeiwen.com/subject/tbxpvdtx.html