线程信号量
线程信号量 vs 进程信号量
主要区别:
特性
|
进程信号量
|
线程信号量
|
头文件
|
#include
|
#include
|
创建
|
semget()
+ 复杂初始化
|
sem_init()
|
使用
|
semop()
|
sem_wait()
/
sem_post()
|
范围
|
系统范围
|
进程内部
|
线程信号量的三个核心函数
1. sem_init() - 初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
- sem: 信号量指针
- pshared: 0表示线程间共享,非0表示进程间共享
- value: 信号量初始值
2. sem_wait() - P操作(等待)
int sem_wait(sem_t *sem); // 阻塞等待 int sem_trywait(sem_t *sem); // 非阻塞尝试
3. sem_post() - V操作(释放)
int sem_post(sem_t *sem); // 释放信号量
简单的线程信号量例子
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t semaphore; // 定义信号量
int shared_data = 0;
void* worker(void* arg) {
int id = *(int*)arg;
printf("线程%d: 等待信号量...\n", id);
sem_wait(&semaphore); // P操作
printf("线程%d: 获得信号量,开始操作共享数据\n", id);
shared_data++;
sleep(2); // 模拟工作
printf("线程%d: 共享数据 = %d\n", id, shared_data);
sem_post(&semaphore); // V操作
printf("线程%d: 释放信号量\n", id);
return NULL;
}
int main() {
pthread_t t1, t2;
int id1 = 1, id2 = 2;
// 初始化信号量,初始值为1(二进制信号量)
sem_init(&semaphore, 0, 1);
printf("创建两个线程...\n");
pthread_create(&t1, NULL, worker, &id1);
pthread_create(&t2, NULL, worker, &id2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("最终共享数据: %d\n", shared_data);
// 销毁信号量
sem_destroy(&semaphore);
return 0;
}
创建两个线程...
线程1: 等待信号量...
线程1: 获得信号量,开始操作共享数据
线程2: 等待信号量... ← 线程2在这里阻塞等待
线程1: 共享数据 = 1
线程1: 释放信号量
线程2: 获得信号量,开始操作共享数据
线程2: 共享数据 = 2
线程2: 释放信号量
最终共享数据: 2
生产者--消费者问题:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
// 信号量定义
sem_t empty; // 空槽位数量
sem_t full; // 已使用槽位数量
sem_t mutex; // 二进制信号量,保护缓冲区
void* producer(void* arg) {
int item = 0;
while (1) {
// 生产一个项目
sleep(1); // 模拟生产时间
sem_wait(&empty); // 等待空槽位
sem_wait(&mutex); // 进入临界区
// 将项目放入缓冲区
buffer[in] = item++;
printf("生产者生产: %d, 位置: %d\n", buffer[in], in);
in = (in + 1) % BUFFER_SIZE;
sem_post(&mutex); // 离开临界区
sem_post(&full); // 增加已使用槽位
}
return NULL;
}
void* consumer(void* arg) {
while (1) {
sem_wait(&full); // 等待有数据的槽位
sem_wait(&mutex); // 进入临界区
// 从缓冲区取出项目
int item = buffer[out];
printf("消费者消费: %d, 位置: %d\n", item, out);
out = (out + 1) % BUFFER_SIZE;
sem_post(&mutex); // 离开临界区
sem_post(&empty); // 增加空槽位
sleep(2); // 模拟消费时间
}
return NULL;
}
int main() {
// 初始化信号量
sem_init(&empty, 0, BUFFER_SIZE); // 初始有5个空位
sem_init(&full, 0, 0); // 初始没有数据
sem_init(&mutex, 0, 1); // 二进制信号量
pthread_t prod, cons;
pthread_create(&prod, NULL, producer, NULL);
pthread_create(&cons, NULL, consumer, NULL);
pthread_join(prod, NULL);
pthread_join(cons, NULL);
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);
return 0;
}