1. 初始化信号量:sem_init
int sem_init(sem_t *sem, intpshared, unsigned intvalue);
参数
sem:指向要初始化的信号量变量地址,sem_t 是信号量的类型。
pshared:共享范围
传 0:线程间共享(最常用),信号量在当前进程的内存中,仅本进程内线程可见。
传非 0:进程间共享,信号量需放在共享内存中,供多个亲缘进程使用。
value:信号量的初始值
互斥场景设为 1(等价于互斥锁)
同步场景设为 0(用于等待事件触发)
资源计数场景设为资源总数(如限制并发数)
2. 销毁信号量:sem_destroy
int sem_destroy(sem_t *sem);
功能:释放信号量占用的系统资源。
注意事项:
必须确保没有线程阻塞在该信号量上时再销毁,否则行为未定义。
销毁后的信号量不能直接使用,必须重新调用 sem_init 初始化后才能再次使用。
3. P 操作(申请资源 / 阻塞等待)
P 操作会将信号量值减 1,根据信号量当前值的不同,分为三个版本:
阻塞版:sem_wait(最常用)
int sem_wait(sem_t *sem);
若信号量值 > 0:立刻将值减 1,函数返回。
若信号量值 = 0:调用线程阻塞挂起,直到信号量值变为 > 0,再执行减 1 并返回。
非阻塞版:sem_trywait
int sem_trywait(sem_t *sem);
若信号量值 > 0:减 1 成功,返回 0。
若信号量值 = 0:不阻塞,立刻返回 -1,errno 置为 EAGAIN。
适用于不能阻塞的场景,获取失败可以去做其他任务。
超时版:sem_timedwait
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
若在超时时间内获取到信号量,减 1 成功返回 0。
超过指定时间仍未获取到,返回 -1,errno 置为 ETIMEDOUT。
4. V 操作(释放资源 / 唤醒等待)
int sem_post(sem_t *sem);
功能:将信号量的值原子性加 1。
如果当前有线程阻塞在该信号量上,会唤醒其中一个等待的线程。
该操作是原子操作,不会出现竞态问题,且可以在信号处理函数中安全调用。