用信号量解决经典同步问题代码
时间: 2024-02-21 15:56:56 浏览: 27
以下是使用信号量解决生产者-消费者问题的代码示例(使用C语言和Linux系统信号量):
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 5 // 缓冲区大小
#define PRODUCER_NUM 2 // 生产者数量
#define CONSUMER_NUM 2 // 消费者数量
#define ITEM_NUM 10 // 每个生产者/消费者生产/消费的数据数量
sem_t empty, full; // 空闲空间和已有数据的信号量
pthread_mutex_t mutex; // 互斥锁
int buffer[BUFFER_SIZE]; // 缓冲区
int in = 0, out = 0; // 生产者和消费者的指针
void *producer(void *arg) {
int id = *(int *)arg;
int i, item;
for (i = 0; i < ITEM_NUM; i++) {
item = rand() % 100; // 生产一个随机数作为数据
sem_wait(&empty); // 等待空闲空间
pthread_mutex_lock(&mutex); // 加锁
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
printf("Producer %d produces item %d\n", id, item);
pthread_mutex_unlock(&mutex); // 解锁
sem_post(&full); // 增加已有数据
sleep(1); // 等待一段时间再生产下一个数据
}
pthread_exit(NULL);
}
void *consumer(void *arg) {
int id = *(int *)arg;
int i, item;
for (i = 0; i < ITEM_NUM; i++) {
sem_wait(&full); // 等待已有数据
pthread_mutex_lock(&mutex); // 加锁
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
printf("Consumer %d consumes item %d\n", id, item);
pthread_mutex_unlock(&mutex); // 解锁
sem_post(&empty); // 增加空闲空间
sleep(1); // 等待一段时间再消费下一个数据
}
pthread_exit(NULL);
}
int main() {
int i;
pthread_t producer_threads[PRODUCER_NUM], consumer_threads[CONSUMER_NUM];
int producer_ids[PRODUCER_NUM], consumer_ids[CONSUMER_NUM];
srand(time(NULL));
sem_init(&empty, 0, BUFFER_SIZE); // 初始化空闲空间为缓冲区大小
sem_init(&full, 0, 0); // 初始化已有数据为0
pthread_mutex_init(&mutex, NULL); // 初始化互斥锁
for (i = 0; i < PRODUCER_NUM; i++) {
producer_ids[i] = i;
pthread_create(&producer_threads[i], NULL, producer, &producer_ids[i]);
}
for (i = 0; i < CONSUMER_NUM; i++) {
consumer_ids[i] = i;
pthread_create(&consumer_threads[i], NULL, consumer, &consumer_ids[i]);
}
for (i = 0; i < PRODUCER_NUM; i++) {
pthread_join(producer_threads[i], NULL);
}
for (i = 0; i < CONSUMER_NUM; i++) {
pthread_join(consumer_threads[i], NULL);
}
sem_destroy(&empty); // 销毁信号量
sem_destroy(&full);
pthread_mutex_destroy(&mutex); // 销毁互斥锁
return 0;
}
```
该代码中,生产者和消费者线程分别调用`producer`和`consumer`函数,其中`arg`参数用于传递线程ID。在`producer`函数中,线程首先生成一个随机数作为数据,然后等待空闲空间信号量`empty`,如果当前空闲空间大于0,则可以添加数据,同时减少空闲空间,增加已有数据信号量`full`。在`consumer`函数中,线程首先等待已有数据信号量`full`,如果当前已有数据大于0,则可以取出数据,同时减少已有数据,增加空闲空间信号量`empty`。在添加和取出数据时,使用互斥锁`mutex`来保证线程安全。最后,使用`sem_destroy`和`pthread_mutex_destroy`函数销毁信号量和互斥锁。