- 一、信号量
- 信号量是一种用于线程间或进程间同步的机制,它可以用来控制对共享资源的访问,协调线程的执行顺序
- 线程间同步机制:让多个线程在执行某个任务时,具有先后顺序的执行
- 信号量的基本概念
- P操作(wait):尝试获取信号量,如果信号量值>0则减1并继续,否则阻塞
- V操作(post):释放信号量,将信号量值加1并唤醒等待的线程
- 操作步骤:头文件include<semaphore.h>
- 初始化信号量
- int sem_init(sem_t *sem, int pshared, unsigned int value);
- 参数:sem:要初始化的信号量的地址(指针);pshared:0表示线程间共享,非0表示进程间共享;value:信号量的初始值(0/1)
- 申请信号量:P操作
- int sem_wait(sem_t *sem);
- 释放信号量:V操作
- int sem_post(sem_t *sem);
- 销毁信号量
- int sem_destroy(sem_t *sem);
- 二、死锁
- 在多线程编程中,当需要同时获取多个锁时,不正确的加锁顺序可能导致死锁。死锁是指两个或多个线程互相等待对方持有的锁,导致所有线程都无法继续执行的情况
- 死锁的四个必要条件
- 请求与保持条件:线程持有至少一个资源,并等待获取其他资源
- 不剥夺条件:已分配给线程的资源不能被其他线程强行夺取
- 循环等待条件:存在一个线程的循环链,每个线程都在等待下一个线程所持有的资源
- 解决方法
- 使用非阻塞锁,一旦线程发现请求的锁被使用,就去释放自己拥有的锁
- int sem_trywait(sem_t *sem)
- 三、进程间通信:IPC机制
- 同一主机进程间通信
- 无名管道(pipe)
- 只能用于同一主机具有亲缘关系的进程间的通信(父子进程)
- 管道的特性:
- 写阻塞:读端和写端都存在,向管道中写数据,当管道满时,发生写阻塞
- 读阻塞:读端和写端都存在,从管道中读数据,若管道为空,则发生读阻塞
- 读返回0:当写端关闭,从管道中读数据,若管道中有数据,则读到数据;若管道中没有数据,read则返回0,不再阻塞
- 管道破裂:读端关闭,向管道中写入数据,发生管道破裂(异常)
- 有名管道(FIFO)
- 操作流程:
- 创建管道文件:mkfifo()
- int mkfifo(const char *pathname, mode_t mode)
- 参数:pathname:管道文件的名称;mode:管道文件的读写执行权限
- 删除管道文件:remove()
- intremove(const char*pathname)