码迷,mamicode.com
首页 > 编程语言 > 详细

C++ 并行编程《一》

时间:2019-08-28 11:16:32      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:函数调用   编程   主线程   return   返回   try   read   err   别名   

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++ 并行编程《一》

标签:函数调用   编程   主线程   return   返回   try   read   err   别名   

原文地址:https://www.cnblogs.com/PPWEI/p/11422424.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!