一、引言
在多线程编程中,经常会使用信号量来控制访问临界资源。
二、线程级信号量
初始化信号量
1
2
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem
:信号量对象指针
pshared
:共享标志(0 表示线程间共享,非 0 表示进程间共享)
value
:信号量初始值(1 表示二元信号量)
返回值:成功返回 0, 失败返回 -1。
等待信号量
1
2
int sem_wait(sem_t *sem); // 阻塞等待
int sem_trywait(sem_t *sem); // 非阻塞尝试
释放信号量
1
int sem_post(sem_t *sem);
销毁信号量
1
int sem_destroy(sem_t *sem);
销毁信号量必须在没有线程等待该信号量时可以。
代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
void * read(void * arg);
void * accu(void * arg);
static sem_t sem_one;
static sem_t sem_two;
static int num;
int main(int argc, char *argv[])
{
pthread_t id_t1, id_t2;
sem_init(&sem_one, 0, 0);
sem_init(&sem_two, 0, 1);
pthread_create(&id_t1, NULL, read, NULL);
pthread_create(&id_t2, NULL, accu, NULL);
pthread_join(id_t1, NULL);
pthread_join(id_t2, NULL);
sem_destroy(&sem_one);
sem_destroy(&sem_two);
return 0;
}
void * read(void * arg)
{
int i;
for(i=0; i<5; i++)
{
fputs("Input num: ", stdout);
sem_wait(&sem_two);
scanf("%d", &num);
sem_post(&sem_one);
}
return NULL;
}
void * accu(void * arg)
{
int sum=0, i;
for(i=0; i<5; i++)
{
sem_wait(&sem_one);
sum+=num;
sem_post(&sem_two);
}
printf("Result: %d \n", sum);
return NULL;
}
三、系统级信号量
创建信号量集
1
2
3
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
key
:信号量键值(通常由 ftok
生成或使用 IPC_PRIVATE
)
nsems
:信号量集中信号量的个数
semflg
:标志位(如 IPC_CREAT
表示不存在则创建,0644
设置权限)
返回值:成功返回信号量集 ID,失败返回 -1
。
信号量控制
1
int semctl(int semid, int semnum, int cmd, union semun arg);
semid
:semget
返回的信号量集 ID。
semnum
:信号量在集合中的索引(0 表示第一个信号量)。
cmd
:操作命令(如 SETVAL
初始化值,IPC_RMID
删除信号量)。
arg
:联合体 semun
,用于传递初始值或获取状态。
返回值:根据 cmd
不同返回结果(如 GETVAL
返回信号量值)。
信号量操作
1
2
3
4
5
6
int semop(int semid, struct sembuf *sops, unsigned nsops);
struct sembuf {
unsigned short sem_num; // 信号量索引
short sem_op; // 操作值(-1 等待锁,+1 释放锁)
short sem_flg; // 标志(如 `SEM_UNDO` 防止死锁)
};
semid
:信号量集 ID。
sops
:操作结构体数组指针,定义对信号量的原子操作。
nsops
:操作结构体数量
返回值:成功返回 0
,失败返回 -1
。