《C++ Concurrency in Action》读书笔记一 多线程与线程管理

简介,c++11 中STL标准加入了对多线程的支持。现在可以直接使用STL::thread来创建线程并且对线程进行管理

Cp1.通过一个hello world的例子引入C++11 中多线程的支持

#include <iostream>
#include <thread>

void hello()
{
    std::cout<<"Hello Concurrency World"<<std::endl;
}

int main()
{
    std::thread t(hello);
    t.join();

    return 0;
}



Cp2.线程管理

1. 基本线程管理

1)std::thread的构造函数支持任何的std::function 比如函数,函数对象,lambda表达式等。作为std::thread的构造函数之参数。

2)线程启动以后可以选择join等待线程函数返回 或者deatch让其自动运行而不等待其返回。

join会等待线程执行结束而回收资源,detach调用之后会让线程成为守护线程资源回收交给runtime library管理

如果不执行join也不执行detach 会导致std::thread对象在退出栈的时候调用std::terminate()强制结束程序。

使用G++ 4.9.2 编译器执行的效果



3)  为了防止线程由于遇到exception而不能调用join来释放std::thread的资源,

可以使用try catch语句在catch中调用t.join在函数退出之前来等待线程结束。

使用类的析构函数来回收资源

#include <iostream>
#include <thread>

class thread_guard{
public:
    thread_guard(std::thread & t_):t(t_)
    {

    }
    ~thread_guard()
    {
        if(t.joinable()){
            t.join();
            std::cout<<"free the resource for the std::thread"<<std::endl;
        }
    }
private:
    std::thread& t;
};
void hello()
{
    std::cout<<"Hello Concurrency World"<<std::endl;
}


int main()
{
    std::thread t(hello);
    thread_guard g(t);

    //do something else.
    return 0;
}


使用RAII tr1::shared_ptr<std::thread> threadptr(thread_function, delete_function);

#include <iostream>
#include <thread>
#include <tr1/memory>


void hello()
{
    std::cout<<"Hello Concurrency World"<<std::endl;
}

void release_thread(std::thread *t)
{
    if(t->joinable())
    {
        t->join();
        std::cout<<"free the resource for the std::thread"<<std::endl;
    }
}

int main()
{
    std::thread * t = new std::thread(hello);
    std::tr1::shared_ptr<std::thread> g(t, release_thread);

    //do something else.
    return 0;
}

4)让线程在后台运行detach()

目标线程就成为了守护线程(daemon threads)驻留后台运行,与之关联的std::thread对象失去对目标线程的关联,无法再通过std::thread对象取得该线程的控制权。调用joinable()返回false。


2.传递参数给线程函数

1)参数默认是以拷贝方式传递给线程函数,就算线程函数的参数列表本身是引用方式,因为std::thread的构造函数默认并不知道线程函数的参数是引用。

这时候可以使用std::ref(parameter)强制以引用方式传递参数。

2)将对象的成员函数传递给std::thread的构造函数

class X{
public:
    void do_something(){};
};

X my_x;
std::thread t(&X::do_something, &my_x)

这等效于调用了my_x.do_something()

3)传递只能move不可copy的参数例如std::unique_ptr

std::unique_ptr<int> p(10);

std::move(p);


3.传递std::thread的管理权

1)std::thread对象类似std::unique_ptr一样是不可copy但是可以move。

注意以下例子 

std::thread t1(some_func1);
std::thread t2(some_func2);
t1 = std::move(t2); //这会导致程序强制结束std::terminate();



2)std::thread可以作为函数的返回值 可以作为函数的参数传递

std::thread f()
{
    void some_function();
    return std::thread(some_function);
}


4.运行时选择创建线程的数量

1)创建复数的线程并等待他们结束

std::vector<std::thread> threads;
for(unsigned i=0; i<20; ++i)
{
    threads.push_back(std::thread(do_work));   
}
std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
2) std::thread::hardware_concurrency() 返回一个程序可以执行的最大线程数。在多核系统上通常是cpu的核心数。
一个并行计算累积的例子

template<typename Iterator, typename T>
struct accumulate_block
{
    void operator()(Iterator first, Iterator last, T& result)
    {
        result = std::accumulate(first, last, result);
    }
};

template<typename Iterator, typename T>
T parallel_accumulate(Iterator first, Iterator last, T init)
{
    unsigned long const length = std::distance(first, last);

    if(!length)
        return init;

    unsigned long const min_per_thread = 25;
    unsigned long const max_thread = (length + min_per_thread - 1)/ min_per_thread;

    unsigned long const hardware_threads = std::thread::hardware_concurrency();

    unsigned long const num_threads = std::min(hardware_threads!=0?hardware_threads:2, max_threads);

    unsigned long const block_size = length/num_threads;

    std::vector<T> results(num_threads);
    std::vector<std::thread> threads(num_threads-1);

    Iterator block_start = first;
    for(unsigned long i=0; i<(num_threads-1); ++i)
    {
        Iterator block_end = block_start;
        std::advance(block_end, block_size);
        threads[i] = std::thread(
            accumulate_block<Iterator, T>(),
            block_start, block_end, std::ref(results[i]));
        block_start = block_end;
    }
    accumulate_block<Iterator, T>()(block_start, last, results[num_threads-1]);
    std::for_each(threads.begin(), threads.end(),
        std::mem_fn(&std::thread::join));

    return std::accumulate(results.begin(), results.end(), init);
}

5. 标示线程

std::thread::id   使用get_it()函数

使用std::cout 输出id

std::cout<<std::this_thread::get_id();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值