请实现一个队列,队列的使用方有生产者(往队列里写数据),同时有消费者(从里面取数据);实现生产与消费的接口函数;需要考虑多线程环境,生产与消费可能同时进行的情况,导致数据不安全的问题;作为消费者,它如何能实时的知道队列里有数据而去进行消费?即消息或者事件实现实时通知。请写一段程序满足以上要求
时间: 2023-04-04 09:00:43 浏览: 66
以下是一个基于线程安全的队列实现,包括生产者和消费者的接口函数以及实时通知机制:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define QUEUE_SIZE 10
typedef struct {
int *data;
int head;
int tail;
int size;
sem_t empty;
sem_t full;
pthread_mutex_t lock;
} Queue;
void queue_init(Queue *q) {
q->data = (int *)malloc(sizeof(int) * QUEUE_SIZE);
q->head = ;
q->tail = ;
q->size = ;
sem_init(&q->empty, , QUEUE_SIZE);
sem_init(&q->full, , );
pthread_mutex_init(&q->lock, NULL);
}
void queue_destroy(Queue *q) {
free(q->data);
sem_destroy(&q->empty);
sem_destroy(&q->full);
pthread_mutex_destroy(&q->lock);
}
void queue_push(Queue *q, int value) {
sem_wait(&q->empty);
pthread_mutex_lock(&q->lock);
q->data[q->tail] = value;
q->tail = (q->tail + 1) % QUEUE_SIZE;
q->size++;
pthread_mutex_unlock(&q->lock);
sem_post(&q->full);
}
int queue_pop(Queue *q) {
sem_wait(&q->full);
pthread_mutex_lock(&q->lock);
int value = q->data[q->head];
q->head = (q->head + 1) % QUEUE_SIZE;
q->size--;
pthread_mutex_unlock(&q->lock);
sem_post(&q->empty);
return value;
}
void *producer(void *arg) {
Queue *q = (Queue *)arg;
for (int i = ; i < 100; i++) {
queue_push(q, i);
printf("producer: %d\n", i);
}
return NULL;
}
void *consumer(void *arg) {
Queue *q = (Queue *)arg;
while (1) {
int value = queue_pop(q);
printf("consumer: %d\n", value);
}
return NULL;
}
int main() {
Queue q;
queue_init(&q);
pthread_t producer_thread, consumer_thread;
pthread_create(&producer_thread, NULL, producer, &q);
pthread_create(&consumer_thread, NULL, consumer, &q);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
queue_destroy(&q);
return ;
}
```
在这个程序中,我们使用了一个循环数组来实现队列,同时使用了信号量和互斥锁来保证线程安全。生产者线程通过调用 `queue_push` 函数往队列里写入数据,消费者线程通过调用 `queue_pop` 函数从队列里取出数据。当队列为空时,消费者线程会被阻塞,直到有数据可供消费;当队列已满时,生产者线程会被阻塞,直到有空间可供写入。
为了实现实时通知机制,我们使用了信号量 `empty` 和 `full`,它们分别表示队列中空闲的空间和已经被占用的空间。当生产者往队列里写入数据时,它会调用 `sem_post(&q->full)` 来通知消费者线程有数据可供消费;当消费者从队列里取出数据时,它会调用 `sem_post(&q->empty)` 来通知生产者线程有空间可供写入。这样,消费者线程就可以实时地知道队列里有数据可供消费,而不需要不断地轮询队列状态。