c++多线程一:什么是多线程

多线程与多核

无论是手机还是pc,都存在着多核,多核cpu可以同时处理多种事情。

尤其是存在着线程可能会阻塞的情况下,使用多线程对于效率有很高的帮助,举个形象的例子,在烧开水的时候这段时间如果是单线程执行,明明在烧开水的时候可以完成其他事情,但是没有办法,单线程只能按照事情的顺序一件件取做。
在这里插入图片描述
目前网络上关于c++多线程相关的教程和讲解并不是很多,甚至在c++的绝大多数书籍中都没有涉及到相关知识的讲解。

因为对于多线程的使用一般都集中在java等更加高级的语言中,这些语言一般也会封装的很友好,像在java中,两个volatile和synchronized关键字就基本上解决了大多数的问题,开发者也不需要太过将精力集中在底层。但是c++之所以还没有被淘汰甚至在编程语言中占有重要的一个席位,就是因为c++一方面可以操控底层的寄存器等,另一方面,在对性能要求比较高的情况下,c++的效率是要高于java的,因为java虚拟机就是用c++来编写的。所以在一些比如服务器等场合,c++依然是主流。

从这段时间的学习来看,还没有一个权威的中文教程可以权威、准确的将c++多线程的知识全部解释清楚,甚至错误还有点多。当然我在学习的时候也会出现一些问题,所以在读者不明白的时候请参考官方c++网站。http://www.cplusplus.com/reference/atomic/atomic/
https://en.cppreference.com/w/cpp/atomic/atomic/

多线程的使用

#include <iostream>
#include <thread>

using namespace std;

void print_task(char n){
    for(int i = 0; i < 500; i++){
        cout << n ;
    }
    cout << endl;
}

int main(){
    std::thread t1(print_task, '+');        // 线程t1执行print_task,参数为'+'
    std::thread t2(print_task, '-');
    t1.join();     // 必须使用join不然会core dump
    t2.join();
    return 0;
}

上图的例子中就是多线程的使用,在函数构建的时候没有什么区别,但是main中,调用了成员函数thread,生成了两个对象t1和t2,这两个线程将同时开启运行,且开启和运行的时间是不确定的。运行的结果如下:
在这里插入图片描述
从结果可以看出来,两个线程确实是符合多线程的特性,即穿插打印出了+和-。

在使用多线程的时候需要注意的点:

  1. 编译的时候需要加上-pthread参数,比如编译上图的test1命令为 g++ test1_simple_case_of_multi_threads.cc -o test1_simple_case_of_multi_threads -pthread
  2. 每一个开启的线程必须都要使用join释放,比如上述的例子,假如t2忘记释放了,就会core dump。这个与java有着显著的区别,首先java是不需要手动释放每一个线程的,而且java中join的作用是等上一个线程结束了再运行下一个线程。至于c++中join的作用到底是什么,暂时还不是很清楚,猜测是资源的释放。但不用,很有可能出错,这里可以看做一种使用的规范。
  3. 多线程需要加上头文件#include <thread>

使用多线程会出现的问题

从上面的例子可以看出,多个线程的执行是没有规律的,可能是t1执行了一会儿之后立马切换到t2执行,这就会导致某些需要不被打断的操作出现问题,比如多个线程对一个全局变量进行++操作,假如线程1对变量a(0)进行++操作之后为1,但是线程2在获得变量a的值时,是线程1在执行++操作之前的值,那么线程2也对变量a(0)进行了++操作,结果也是为1,于是两个线程对a进行++操作之后,a的结果依然为1。这就与我们的预期不符合。

再举个例子,假如每个线程需要输出一段字符串,如下:

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>    // 需要添加mutex头文件

using namespace std;
mutex mtx;

void thread_task(int n){
    for(int i = 0; i < 10000; i++){}            // 假设此处为各个线程要执行的代码空间,此部分各个线程互不干扰

    cout << "I am thread " <<  n <<  '\n';      // 但是该部分字符串是需要在终端上不被打断地输出的,假设此处为多个线程需要独立执行的部分
}

int main(){
    thread threads[5];                          // 创建一个线程数组
    for(int i = 0; i < 5; i++){                 
        threads[i] = thread(thread_task, i);    // 用数组的方式创建线程
    }
 
    for(auto& t: threads){                      // c++的循环方式,用于遍历数组中的元素
        t.join();
    }

    return 0;
}

输出的内容对于人来说自然希望是完整的,但是现实的情况却是混乱的:
在这里插入图片描述
那么能不能有一种方法可以让多线程在运行的时候,针对某部分的内容加上锁,让该部分内容在运行的时候是不被打断的呢?于是多线程另外一个重要的概念出来了——mutex互斥量。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值