linux多线程之POSIX信号量
目录
1. 信号量的概念
2. POSIX 信号量相关函数
初始化信号量 :sem_init
获取信号量 :sem_wait
释放信号量 : sem_post
销毁信号量 :sem_destroy
3. 示例代码
POSIX 信号量是 POSIX 操作系统标准定义的一种同步原语,用于多线程(以及多进程)环境中的同步与互斥操作。在多线程编程中,POSIX 信号量有助于控制对共享资源的访问,防止竞态条件的发生。
1. 信号量的概念
信号量本质上是一个整型变量,它通过一个计数器来控制对共享资源的访问。当线程需要访问共享资源时,它会尝试获取信号量(将计数器减 1)。如果计数器的值大于 0,获取操作成功,线程可以继续执行;如果计数器的值为 0,线程将被阻塞,直到其他线程释放信号量(将计数器加 1)。
2. POSIX 信号量相关函数
初始化信号量 :sem_init
- 函数原型:
int sem_init(sem_t *sem, int pshared, unsigned int value);
- 功能:初始化一个未命名的信号量。
- 参数:
sem
:指向要初始化的信号量变量的指针。pshared
:用于指定信号量的共享方式。如果pshared
的值为 0,表示这个信号量是当前进程内的线程共享;如果pshared
非 0,表示这个信号量可以在多个进程间共享(常用于进程间通信场景)。在多线程场景中,通常设置为 0。value
:指定信号量的初始值。这个值表示可用资源的数量。例如,如果value
为 1,通常用于实现互斥锁(因为同一时间只允许一个线程获取信号量,即只有一个线程能访问共享资源);如果value
大于 1,则可以允许多个线程同时访问共享资源,具体数量由value
决定。
- 返回值:成功时返回 0,失败时返回 -1,并设置
errno
以指示错误原因,如EINVAL
(无效的参数)或ENOMEM
(内存不足)。
获取信号量 :sem_wait
- 函数原型:
int sem_wait(sem_t *sem);
- 功能:尝试获取信号量。如果信号量的值大于 0,函数将信号量的值减 1,然后返回,调用线程可以继续执行;如果信号量的值为 0,调用线程会被阻塞,直到信号量的值变为大于 0。
- 参数:
sem
指向要操作的信号量变量的指针。 - 返回值:成功时返回 0,失败时返回 -1,并设置
errno
来表示错误原因,如EINTR
(操作被信号中断)。
释放信号量 : sem_post
- 函数原型:
int sem_post(sem_t *sem);
- 功能:释放信号量,将信号量的值加 1。如果有其他线程正在等待该信号量(即信号量的值为 0 且有线程在
sem_wait
中阻塞),则会唤醒其中一个等待线程,使其能够获取信号量并继续执行。 - 参数:
sem
指向要操作的信号量变量的指针。 - 返回值:成功时返回 0,失败时返回 -1,并设置
errno
指示错误原因,如EINVAL
(无效的信号量)。
销毁信号量 :sem_destroy
- 函数原型:
int sem_destroy(sem_t *sem);
- 功能:销毁一个已初始化的信号量,释放与之相关的所有资源。在销毁信号量之前,应确保没有线程正在等待该信号量,并且所有对该信号量的操作已经完成。
- 参数:
sem
指向要销毁的信号量变量的指针。 - 返回值:成功时返回 0,失败时返回 -1,并设置
errno
指示错误原因,如EBUSY
(信号量正在被使用)。
3. 示例代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>// 定义共享资源和信号量
int shared_resource = 0;
sem_t semaphore;// 线程函数
void* increment_shared_resource(void* arg) {// 获取信号量sem_wait(&semaphore);shared_resource++;printf("Thread incremented shared_resource to %d\n", shared_resource);// 释放信号量sem_post(&semaphore);return NULL;
}int main() {const int num_threads = 5;pthread_t threads[num_threads];// 初始化信号量if (sem_init(&semaphore, 0, 1) != 0) {perror("Semaphore initialization failed");return 1;}// 创建线程for (int i = 0; i < num_threads; i++) {if (pthread_create(&threads[i], NULL, increment_shared_resource, NULL) != 0) {perror("Thread creation failed");return 1;}}// 等待所有线程完成for (int i = 0; i < num_threads; i++) {if (pthread_join(threads[i], NULL) != 0) {perror("Thread join failed");return 1;}}// 销毁信号量sem_destroy(&semaphore);return 0;
}