跳至主要內容

多线程 - 线程基本概念

LincZero大约 5 分钟

多线程 - 线程基本概念

参考:

概念

并行、并发

并行

  • 两个或更多的任务同时发生。这里可以在任务管理器中查看线程

并发

  • 硬件并发
  • 同时可以干多件事、提高性能

区别

  • 并行不等于并发,并发是物理上的同时执行,并行是并发的子级
  • 旧计算机只有单核cpu,由操作系统调度,每个时间片进行多次任务切换,这种上下文切换需要额外时间开销 只能实现并行,是并发的假象
  • 现在是的cpu,多核指一个芯片上多个cpu(双核、4核、8核、16核) 这个可以在 “任务管理器 > 性能 > CPU > 右侧右键 > 将图形更改为 > 逻辑处理器” 中查看 能实现真正意义上的并发

程序、进程、线程

程序(可执行程序)

  • windows下,扩展名为exe
  • linux下,执行ls -la后显示rwx中的x表示执行权限

进程

  • 进程是运行着的可执行程序
  • 每个进程都会有一个PID
  • 一个可执行程序运行起来了,就创建了一个进程。如果运行两次,则会创建两个进程

线程

  • 主线程:每个进程都有且只有一个自动生成的主线程,主线程也是main函数所在线程
  • 非主线程:除了主线程,可以通过代码来创建其他线程。线程是用来执行代码的
  • 缺点:线程不是越多越好,每个线程都需要一个独立的堆栈空间(>1M)且切换需要额外时间开销,不建议超过200~300个
  • 使用场景:可能阻塞或响应比较慢的代码、网络方面的操作(多线程/异步编程)

线程id(std::this_thread::get_id()

  • 概念:每个线程都有一个不重复的线程id
  • 使用:线程id可以通过std::this_thread::get_id();来获取
  • 应用:调试时可以打印线程id来方便调试

进程与线程 查看与查询

查看方法

  • 可以在 “任务管理器 > 性能 > CPU > 右侧进程与线程” 中查看进程数和线程数
  • 可以在 “任务管理器 > 进程” 中查看具体进程,且会折叠一个应用中的多个进程
  • 可以在 “任务管理器 > 用户” 中查看具体进程,但不会显示Winodws进程,且不会折叠一个应用中的多个进程

通过进程/线程查询

  • 通过PID查找端口和协议
  • CMD方法
    • netstat -ano,列举程序PID和对应的网络端口
    • netstat -ano | findstr 6636,管道符筛选指定程序PID
  • PID查找端口和协议:火绒剑方法
    • 图形化界面更直观,也很容易用

并发的实现

两种实现方法

两种并发方法

  • 多进程并发
    • 进程之间通信(同一个电脑上:管道、文件、消息队列、共享内存。不同电脑上:socket通信技术)
  • 多线程并发
    • 有点类似于轻量级进程的感觉,但一个进程中所有线程共享地址空间(共享内存)
    • 线程之间通信。全局变量、指针、引用等都可以在线程之间传递
    • 所有使用多线程开销远远小于多进程
  • 比较
    • 建议优先使用多线程,开销小速度快
    • 但要小心处理数据一致性问题,线程间的共享变量可能造成死锁的出现

多线程 vs 异步编程

参考:【博客园】异步编程与多线程编程的联系和区别open in new window

博文很不错,推荐一看


  • 共同点

    • 异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性
  • 不同点

    • (1) 线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

      • 多线程优点:线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。

      • 多线程缺点:线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现

    • (2) 异步操作无须额外的线程负担,并且使用回调的方式进行处理

      • 异步操作优点:在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少共享变量的数量),减少了死锁的可能

      • 异步操作缺点:编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些 初入,而且难以调试。

  • 总结

    • 在实际设计时,我们可以将两者结合起来
    • 异步特别适用于大多数IO密集型的应用程序
    • 线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行

C++11新标准线程库

以前版本

以往语言本身不支持,通过操作系统接口来实现,这些多线程代码不能跨平台,需要用一些库才能跨平台

winodws:
CreateThread();
_beginthread();
_beginthreadexe();
    
linux:
pthread_create();

C++11

C++11开始,提供了对多线程的支持,多线程代码能够跨平台实现