Linux多线程:创建、回收与互斥同步

一、线程的创建

线程用 pthread_create 来创建,这是最基础的接口。

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

void *(*start_routine) (void *), void *arg);

四个参数:thread保存线程ID,attr是线程属性(传NULL用默认),start_routine是线程要执行的任务函数,arg是传给任务函数的参数。成功返回0,失败返回错误码。

有两个注意点:编译时必须加 -pthread 链接线程库;创建线程的主进程不能先于线程结束,否则线程直接就没了。

写个最简单的例子:

#include <stdio.h>

#include <pthread.h>

void *task(void *arg)

{

printf("子线程运行中\n");

pthread_exit(NULL);

}

int main(void)

{

pthread_t tid;

pthread_create(&tid, NULL, task, NULL);

sleep(1); // 主线程不能先结束

return 0;

}

二、线程退出与资源回收

线程退出有三种方式:线程函数执行完return、所在进程结束、调用 pthread_exit 主动退出。

退出之后涉及资源回收,这里分两种属性。

分离属性:用 pthread_detach(tid) 设置,线程结束后由操作系统自动回收,不需要其他线程管。适合其他线程没机会回收它的场景。

非分离属性:这是默认属性,线程结束后必须被其他线程回收,用 pthread_join 。

int pthread_join(pthread_t thread, void **retval);

阻塞等待指定线程结束并回收资源,retval用来接收线程退出状态,不关心就传NULL。成功返回0,失败返回非0。

三、线程的同步与互斥

线程之间通信很方便,全局变量、队列、pthread_create传参、条件变量都可以。但问题也来了------多个线程同时访问同一个共享资源,会产生竞争。

这里有两个概念要分清:

临界资源:多个线程能同时访问的区域,比如全局变量、全局队列、文件、数据库

临界区:访问临界资源的那段代码

解决办法是互斥锁,保证同一时间只有一个线程能进入临界区。

互斥锁的使用流程:

  1. 创建锁对象: pthread_mutex_t

  2. 初始化: pthread_mutex_init()

  3. 进入临界区前加锁: pthread_mutex_lock()

  4. 出临界区解锁: pthread_mutex_unlock()

  5. 用完销毁: pthread_mutex_destroy()

int pthread_mutex_init(pthread_mutex_t *restrict mutex,

const pthread_mutexattr_t *restrict attr);

初始化锁,mutex是锁对象地址,attr传NULL用默认属性。

经典的卖票例子,三个窗口卖10张票,不加锁会超卖:

#include <stdio.h>

#include <pthread.h>

#include <unistd.h>

int ticket = 10;

pthread_mutex_t mutex;

void *sell(void *arg)

{

char *win = (char *)arg;

while (1)

{

pthread_mutex_lock(&mutex);

if (ticket > 0)

{

printf("%s 卖出第 %d 张\n", win, ticket);

ticket--;

}

else

{

pthread_mutex_unlock(&mutex);

break;

}

pthread_mutex_unlock(&mutex);

}

pthread_exit(NULL);

}

int main(void)

{

pthread_t t1, t2, t3;

pthread_mutex_init(&mutex, NULL);

pthread_create(&t1, NULL, sell, "窗口1");

pthread_create(&t2, NULL, sell, "窗口2");

pthread_create(&t3, NULL, sell, "窗口3");

sleep(2);

pthread_mutex_destroy(&mutex);

return 0;

}

最后是线程同步。互斥解决的是排他访问,同步解决的是执行顺序------让多个线程在执行某些任务时有先后关系。实现同步的方法是信号量。

相关推荐
xixiaoyunya9 分钟前
虚拟机备份怎么做:镜像级与文件级搭配的完整实操方案
linux·运维·网络
墨家句子11 分钟前
服务器被反复尝试登录之后:fail2ban 加密钥登录的五道加固
linux·后端
代码山河13 分钟前
Java学习路线图:2026年最新版,从入门到架构师
java·学习·架构·教程·面向对象·项目
anew___13 分钟前
《从零手写操作系统 (30):环境变量与进程上下文——export/unset与继承语义》
java·开发语言·网络·jvm·算法
阿明615 分钟前
进程替换【Linux】
linux·运维·服务器
sunoo-22919 分钟前
【嵌入式Linux驱动学习】Day1-Day2 全流程梳理:环境搭建→U-Boot→内核→根文件系统→驱动基础
linux·运维·驱动开发·笔记·学习·阿里云·恩智浦
垆边人似月.25 分钟前
城市连通性(200分 / 并查集)
数据结构·算法·图论
我命由我1234526 分钟前
Photoshop - Photoshop 使用简单的选择工具
学习·职场和发展·产品运营·求职招聘·职场发展·学习方法·photoshop
UIU11436 分钟前
头文件可以防什么错?运用头文件做声明
c++·学习·c#
Gust of wind40 分钟前
串与KMP模式匹配:存储结构、基本操作、next数组手算
c语言·数据结构·后端·算法