C++ 并行编程《一》

Posted ppwei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 并行编程《一》相关的知识,希望对你有一定的参考价值。

1.最简单的C++多线程程序

#include <iostream>
#include <thread>

void do_something()

    std::cout << "func do_something..." << std::endl;


int main(int argc, char *argv[])


    std::thread my_thread(do_something);
    std::cout << "main thread" << std::endl;
    my_thread.join();
    return 0;

2.在C++标准中,std::thread可以和任何可调用(callable)类型一同工作,所以,我们可以给std::thread构造函数传递一个带有函数调用操作符的类实例,代替直接传入的函数。

#include <iostream>
#include <thread>

void do_something()

    std::cout << "func do_something" << std::endl;


class background_task

public:
    void operator()() const
    
        do_something();
    
;

int main(int argc, char *argv[])

    background_task bt;
    std::thread my_thread(bt);      /* 传入一个类实例 */
    std::cout << "main thread" << std::endl;
    my_thread.join();

    return 0;

3.等待线程结束,C++有两种线程结束的方法(join、detach)。对于detach()方法来讲,即使线程实例被主线程销毁,线程依旧可以后台执行,直到自行结束。

而对于join()方法,主线程会等待子线程的执行,并获得子线程的返回值。问题是,我们在什么地方等待子线程结束,如果发生异常,怎样保证子线程依旧能够正确结束。一种方法如下:

#include <iostream>
#include <thread>

void do_something()

    std::cout << "func do_something..." << std::endl;


class background_task

public:
    void operator()()
    
        do_something();
    
    background_task(int val)
    
        std::cout << "background_task constructor init" << std::endl;
    
;

int main(int argc, char *argv[])

    int init_val = 0;
    background_task bt(init_val);

    std::thread my_thread(bt);

    try
    
        std::cout<<"err occured here"<<std::endl; /* 错误发生位置 */
    
    catch (...)
    
        my_thread.join();                         /* 为了保证线程在异常情况下也能正常结束 */
        throw;
    
    my_thread.join();                             /* 计划结束位置 */
    return 0;

4.使用try/catch方式结束进程,不仅使代码阅读性降低,而且容易将作用域搞乱,因此需要一种更高明的方法。这样做的方法之一是使用资源获取即初始化(RALL)惯用语法。

如下:

#include <iostream>
#include <thread>

class thread_guard

    std::thread &t;           /* 定义一个别名,将传入的线程复制给它 */

public:
    explicit thread_guard(std::thread &t_) : t(t_) 
    ~thread_guard()
     /* 将进程结束操作和类资源释放绑定 ,只要类被释放,线程就会结束 */
        if (t.joinable())
        
            t.join();
        
    
    thread_guard(thread_guard const &) = delete;
    thread_guard &operator=(thread_guard const &) = delete;
;

void do_something()

    std::cout << "func do_something" << std::endl;


struct func

    int &i;
    func(int &i_) : i(i_) 
    void operator()()
    
        do_something();
    
;

/* 一个简单明了的,能够保证在异常情况下也能正常结束线程的方法 */
int main(int argc, char *argv[])

    int init_val = 0;
    func my_func(init_val);
    std::thread my_thread(my_func);
    thread_guard g(my_thread);
    return 0;                          /* 主线程结束后,会销毁局部变量, 在g被销毁时,会等待子线程结束 */

 

以上是关于C++ 并行编程《一》的主要内容,如果未能解决你的问题,请参考以下文章

C++ 并行编程中的“锁”难题

虚幻4与现代C++:基于任务的并行编程与TaskGraph入门

虚幻4与现代C++:基于任务的并行编程与TaskGraph入门

使用并行编程 C++ 计算/访问向量

C++实战之OpenCL 并行优化编程从零学起系列文章

c++多线程编程:实现标准库accumulate函数的并行计算版本