第9章 多线程编程
本章将分为两大部分进行讲解,第一部分将引出线程的使用场景及基本概念,通过示例代码来说明一个线程创建到退出到回收的基本流程。第二部分则会通过示例代码来说明如果控制好线程,从临界资源访问与线程的执行顺序控制上引出互斥锁、信号量的概念与使用方法。
9.1 线程的使用
9.1.1 为什么要使用多线程
在编写代码时,是否会遇到以下的场景会感觉到难以下手?
要做2件事,一件需要阻塞等待,另一件需要实时进行。例如播放器:一边在屏幕上播放视频,一边在等待用户的按键操作。如果使用单线程的话,程序必须一会查询有无按键,一会播放视频。查询按键太久,就会导致视频播放卡顿;视频播放太久,就无法及时响应用户的操作。并且查询按键和播放视频的代码混杂在一起,代码丑陋。
如果使用多线程,线程1单独处理按键,线程2单独处理播放,可以完美解决上述问题。
9.1.2 线程概念
所谓线程,就是操作系统所能调度的最小单位。普通的进程,只有一个线程在执行对应的逻辑。我们可以通过多线程编程,使一个进程可以去执行多个不同的任务。相比多进程编程而言,线程享有共享资源,即在进程中出现的全局变量,每个线程都可以去访问它,与进程共享“4G”内存空间,使得系统资源消耗减少。本章节来讨论Linux下POSIX线程。
9.1.3 线程的标识pthread_t
对于进程而言,每一个进程都有一个唯一对应的PID号来表示该进程,而对于线程而言,也有一个“类似于进程的PID号”,名为tid,其本质是一个pthread_t类型的变量。线程号与进程号是表示线程和进程的唯一标识,但是对于线程号而言,其仅仅在其所属的进程上下文中才有意义。
获取线程号
#include <pthread.h>
pthread_t pthread_self(void);
成功:返回线程号
在程序中,可以通过函数pthread_self,来返回当前线程的线程号,例程1给出了打印线程tid号。
使用GIT下载所有源码后,本节源码位于如下目录:
01_all_series_quickstart\
04_嵌入式Linux应用开发基础知识\
source\13_thread\01_文档配套源码\Pthread_Text1.c
测试例程1:(Phtread_txex1.c)
1 #include <pthread.h>
2 #include <stdio.h>
3
4 int main()
5 {
6 pthread_t tid = pthread_self();//获取 主线程的tid号
7 printf("tid = %lu\n",(unsigned long)tid);
8 return 0;
9 }
**注意:**因采用POSIX线程接口,故在要编译的时候包含pthread库,使用gcc编译应gcc xxx.c -lpthread 方可编译多线程程序。
编译结果:
![]()
图 9.1 例程1编译结果
9.1.4 线程的创建
怎么创建线程呢?使用pthread_create函数: