ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【 linux 】线程互斥与同步

2026/9/4 5:08:53 拓冰建站 浏览量
【 linux 】线程互斥与同步 目录1. 线程本质2. 线程互斥2.1 信号量2.2 认识锁的接口2.3 理解锁3.线程同步3.1 条件变量1. 线程本质在用户层封装轻量级进程形成原生线程库pthread库是动态库也是ELF库动态库需要加载到内存。线程的概念是在库中定义的那在库中就一定有多个创建好的线程库当然也要管理线程先描述再组织struct tcb -- pthread_create { 线程状态 线程id 线程独立的栈结构 线程栈大小 ... }2. 线程互斥先区分几组概念临界资源多线程执行流被保护的共享的资源就叫做临界资源临界区;每个线程内部访问临界资源的代码叫做临界区互斥:任何时刻互斥保证有且只有一个执行流进入临界区访问临界资源通常对临界资源起保护作用原子性:不会被任何调度机制打断的操作该操作只有两态要么完成要么未完成2.1 信号量本质是一个计数器用来表明临界资源中资源的数量。可以用电影院买票来理解想访问临界资源都得先买票进程访问临界资源先申请信号量本质是对资源的预定机制。信号量本身就是共享资源信号量只有0和1两态的信号量叫做二元信号量也就是互斥数据不一致现象int ticket100; void* Routine(void* args) { char* id(char*)args; while(1) { if(ticket0) { usleep(1000); printf(%s sells ticket:%d,s,id); ticket--; } else break; } return nullptr; }可以看到票数减到负数ticket全局资源没有加保护就会产生并发问题线程安全问题。需要加锁来解决2.2 认识锁的接口全局pthread_mutex_t mutexPTHREAD_MUTEX_INITIALIZER局部int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);申请锁释放锁int pthread_mutex_lock(pthread_mutex_t*mutex);int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);竞争申请锁多线程都得先看到锁锁本身就是临界资源!!申请锁的过程必须是原子的失败:阻塞挂起申请执行流成功继续向后运行访问临界区代码访问临界资源锁提供的能力的本质:执行临界区代码由并行转换成为串行对临界资源的保护本质就是用锁对临界区代码进行保护可以想象成自习室加锁之后临界区代码是允许线程切换的。但是因为我当前线程并没有释放锁我是持有锁被切换的即便我不在!其他线程也得等我回来执行完代码释放锁其他线程才能展开锁的竞争进入临界区2.3 理解锁1.硬件级实现关闭时钟中断2.软件级实现为了实现互斥锁操作.大多数体系结构都提供了swap或exchange指令,该指令的作用是把寄存器和内存单无的数据相交换如果把一个变量的内容交换到CPU寄存器内部本质是:把该变量的内容获取到当前执行流的硬件上下文中当前CPU寄存器的硬件上下文(其实就是各个寄存器的内容)属于:进程/线程私有的!!!!!!我们用swapexchange将内存中的变量交换到CPU的寄存器中:本质是当前线程/进程在获取锁因为是交换不是拷贝!!!所以1只有一份!!所以谁申请到谁持有锁!!3.线程同步锁的技术也带来了新的问题如果一个线程高频的申请锁没有做有效的动作其他线程又申请不到就会产生线程饥饿问题。为了解决线程饥饿就需要制定新的方案1.不能立即申请第二次2.外边的人进行排队退出的人必须跑到队列的尾部进行二次申请在保证自习室安全的前提下让所有的执行流访问临界资源按照一定的顺序进行访问资源!!线程同步!!3.1 条件变量当一个线程互斥地访问某个变量时它可能发现在其它线程改变状态之前它什么也做不了。例如一个线程访问队列时发现队列为空它只能等待只到其它线程将一个节点添加到队列中。这种情况就需要用到条件变量举个放苹果的例子接口#include pthread.hint pthread_cond_destroy(pthread_cond_t)*cond);int pthread cond init(pthread cond t *restrict cond, const pthread condattr t *restrict attr);pthread_cond_t cond PTHREAD_COND_INITIALIZER;int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t*restrict mutex)在指定的条件变量下等待int pthread_cond_broadcast(pthread_cond_t *cond);唤醒在指定条件变量下等待的所有的线程int pthread_cond_signal(pthread_cond_t *cond);唤醒在该条件变量下等待的一个线程点个关注不迷路