前言
从本篇文章开始,将开始Linux多线程的知识,是重点中的重点,概念可能不容易理解,比较难消化,但只要多复习,必定会拿下多线程。
以下是本篇文章正文内容,下面案例可供参考
一、线程的概念
概念定义:在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”。
在我个人理解:多线程,就是进程当中的多个执行流。比如一个程序的代码当中需要计算1加到100的值,我们可以把这一整个进程分成许多步骤,每个步骤执行各自的代码,干不同的工作来完成,每个步骤就可以看作是一个线程。如可以把1加到100分成10个线程来做,第一个线程计算1加到10的结果,第二个计算11加到20的结果,以此类推。
在之前学习的进程中,PCB中有个变量叫pid,它是用来表示进程号的,但是,在多线程中,我们所说的pid指的是线程号(也成为轻量级进程),但在内核当中是没有线程这个概念的,线程是c标准库当中的概念。PCB中还有一个tgid,它指的是线程组id,对应的就是进程id。
可以通过下图来理解线程的概念:
对于主线程而言:pid = tgid
对于工作线程而言:同一个线程组当中的tgid是相等的,标识同一个进程。pid是不同的,表示不同的线程。
线程标识符的理解见下图:
线程的优缺点:
多进程与多线程的对比:
二、线程控制
1.线程创建
线程的创建需要调用pthread_create函数:
pthread_create函数详解:
对于线程入口函数参数(arg)传递的问题,需注意以下几点:
1.线程入口函数的参数不要传递临时变量(需要在堆上开辟空间)
2.传递堆上开辟的空间,在线程不使用的情况下,需要对空间进行释放
3.线程入口函数的参数不仅仅可以传递内置类型,也可以传递自定义类型(类的实例化对象,类的this指针,结构体指针)
实例分析(代码演示):
代码执行结果:循环打印两条语句
使用ps aux(查看进程信息)命令和pstack(查看进程调用堆栈)命令后:
top -H -p [进程号]:可以查看当前进程中所有线程占用cpu资源的信息
2.线程终止
线程终止与进程终止类似,作用是结束一个正在运行的线程。
线程终止的方式有三种:
①线程入口函数的return返回,当前线程就退出了
②调用pthread_exit函数,谁调用谁退出
③调用pthread_cancel函数,可以退出指定线程
3.线程等待
因为线程在创建时,线程默认的属性是joinable属性,joinable会导致在线程退出时,其资源不会被操作系统回收,需要其它线程来进行线程等待,回收自己退出的资源(即线程在共享区当中的资源没有释放)
线程等待函数:pthread_join
线程调用pthread_join线程等待函数的等待方式为阻塞等待,也就是当主线程调用pthread_join函数等待线程退出时,如果线程一直没有退出,pthread_join函数就会阻塞(一直等待,直到要等待的线程退出时,才会继续执行下面的代码)。
4.线程分离
所谓线程分离,就是为线程设置分离属性。
当一个线程从joinable属性被设置成了分离属性(detach),当前这个线程在退出时,操作系统就会回收线程退出的资源,不需要其他线程回收。
线程分离函数:pthread_detach函数