信号量POSIX

50 阅读2分钟

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必须由加锁线程解锁
用途线程/进程同步临界区保护