Semaphore 信号量是用于多线程和多进程数据同步的机制,控制对共享资源的访问。
信号量分为:
- 有名信号量,用于进程同步IPC
- 无名信号里,用于线程同步,或共享内存
或
- 二值信号量:0或1
- 计数信号量:
有名信号量API:
#include <semaphore.h> // POSIX
#incldue <fcntl.h> //O_CREATE 标识
//创建/打开信号量
sem_t * sem_open(const char* name,int oflag,mode_t mode,unsigned int size);
//信号量操作
//1.P操作,申请资源:如果信号量>0时,则-1并继续,如果=0时,则阻塞
int sem_wait(sem_t* sem);//阻塞直到信号量>0
int sem_trywait(semt_t* sem);//非阻塞版本,信号量=0时,返回-1
int sem_timewait(sem_t* sem,const struct timespec*abs_timeout);//带超时
//2.V操作,释放资源:信号量+1,并唤醒等待的进程或线程
int sem_post(sem_t* sem);
//释放
int sem_close(sem_t* sem);//关闭信号量,不会删除,仍可被其他进程使用
int sem_unlink(sem_t* sem);//删除信号量,在所有进程关闭后生效
无名信号量
sem_t sem;
sem_init(&sem,0,1);//第二个参数=0表示线程间共享
sem_wait(&sem);
sem_post(&sem);
sem_destroy(&sem):
注意
信号量残留问题:程序崩溃后,有名信号量可能残留在系统中 解决:程序启动调用sem_unlink清理旧信号量
推荐封装:使用 RAII 模式管理信号量生命周期
适用场景:生产者-消费者模型、资源池限流等。
信号量与互斥锁
互斥锁:同一时刻只允许一个线程访问某个共享资源。或者说一个互斥锁同一时刻只能由一个线程拥有。用于保护共享资源的临界区
信号量:允许多个线程同时访问共享资源,最大并发数量由信号量的值决定。(主要目的是提高并发性能,比如并发读取(如只读数据),并发访问(如线程池的任务队列),同时数据库连接池最大连接数量限制,避免资源过载)
| 特性 | 信号量 | 互斥锁 |
|---|---|---|
| 计数 | 支持(可大于 1) | 只能是 0 或 1 |
| 所有者 | 无(任何线程可 post) | 必须由加锁线程解锁 |
| 用途 | 线程/进程同步 | 临界区保护 |