天天看点

C++多线程之旅-初入C++多线程

目录

      • 走进线程
        • 多进程编程和多线程编程
      • 从hello world开始
        • 启动线程
        • 传入参数
      • 总结

走进线程

最近狂喊的 AMD YES,就是一个极强的线程撕裂者。推出的移动端CPU都已经达到了8核16线程,但是很多应用对多线程优化不好,导致多核性能更强的AMD在有的方面还不如牙膏厂-Intel。如何提升多线程编程能力,就需要大量积累。尤其是在服务器编程方面,我们实验室购置的服务器都是48核了,如果还是依靠单线程那就显得太low了。

多进程编程和多线程编程

多进程编程和多钱程编程,都可以使用并行机制来提升系统的运行效率。二者的区别在于运行时所占的内存分布不同,

多钱程是共用一套内存的代码块区间;而多进程是各用一套独立的内存区间。但是多进程的缺点就是创建一个进程成本很高,而且系统对进程数量有限制,不允许无限制的增长。

C++多线程之旅-初入C++多线程

多线程编程的优点是效率较高一些,适用于批处理任务等功能;不足之处在于,任何一个线程崩溃都可能造成整个进程的崩溃,因为它们共享了进程的内存资源池。

C++多线程之旅-初入C++多线程

学习多线程必须了解操作系统中,关于互斥的有关内容。

从hello world开始

namespace dyj01 {
    int	 i = 0;
    void hello() {
        std::cout << "hello world : " << ++i << endl;
    }
    void test() {
        std::thread t_1( hello );
        std::thread t_2( hello );
        t_1.join();
        t_2.join();
    }
}  // namespace dyj01
           

使用关键字

thread

声明线程,然后传入需要进行多线程的函数名称即可。

C++有一个特点就是解析语法,任何能够解析为声明的都要被解析为声明。

std::thread my_thread(back_task());

这就会导致C++解析为一个函数的声明。解决办法是加上一个小括号或者使用大括号,其中小括号是声明这不是一个类型,避免被解析为声明;而大括号是强制不允许转换。

这里传入的函数可以一下几种类型:

  1. lambda表达式:

    [](int x) { cout << x << endl; }

  2. 普通函数
  3. 成员函数

启动线程

可以显示使用两种方式启动线程:

  1. join()

    :主线程等待子线程结束之后才可以结束(结合)
  2. detach()

    :主线程不在与子线程一致,子线程可以自动执行(分离)

但是在线程开始之后没有进行

join()

detach()

调用会出现意外,所以我们可以采用RAII的资源管理方法对线程进行管理。而且一旦调用过一次

join()

或者

detach()

就不能再次调用了,所以可以调用

joinable()

函数判断是否可以调用

join()

detach()

if(t.joinable())
	t.join();
           

传入参数

线程可以启动了,但是对于一些需要传参的函数来说这样是不能正确执行的,所以在定义多线程是可以传入参数。

thread t1(fun, x);

其中x就是传入的参数值。

但是所有线程传入的值都是pass-by-value,如果需要传入引用则需要调用std中的ref函数来进行包装。

thread t1(fun, ref(x));

此时传入的x就是一个引用了。

在C++11中引入了多线程,一起来的还有右值引用。对于多线程来说

thread

实例是只可以移动不可以复制的,所以如果我们需要转移线程的所有权必须使用右值引用,比如

thread t1(fun); // t1拥有线程所有权
thread t2(move(t1)); // 通过移动构造函数将线程所有权转移到了t2
thread t3 = t2;	// 通过移动赋值函数将线程所有权转移到t3
           

如果此时再给

t3

赋值一个别的线程,那么原有的线程就会被终结。

那么如何来验证上面这个例子呢,就需要知道每个线程的线程号,这相当于你的身份证一样是唯一的。我们就来看一下上述的这个结论是否正确吧。

C++多线程之旅-初入C++多线程

确实这三个实例的线程号是相同的,并且可以主线程还有专门的一个标识,如果是执行主线程那么执行结果会不一致,

master_thread

总结

C++在其他语言都推出多线程很久之后,才推出自己的多线程。*而且很多人会考虑一个问题就是既然多线程是一个实例,可不可以放到容器中呢?*答案是当然可以,而且在后面线程池部分全靠线程容器来实现的。这是多线程的第一部分,应该后面还有6章左右,这也是我的一个总结,也希望能够帮助到别人,谢谢!