多线程并发应用程序有一个经典的模型,即生产者/消费者模型。系统中,产生消息的是生产者,处理消息的是消费者,消费者和生产者通过一个缓冲区进行消息传递。生产者产生消息后提交到缓冲区,然后通知消费者可以从中取出消息进行处理。消费者处理完信息后,通知生产者可以继续提供消息。
要实现这个模型,关键在于消费者和生产者这两个线程进行同步。也就是说:只有缓冲区中有消息时,消费者才能够提取消息;只有消息已被处理,生产者才能产生消息提交到缓冲区。
我们用一个队列来做这个缓冲区,产生的消息我们放到这个队列中去,如果这个队列满了,则不放入消息,我们这个队列大小是10,能够存放10条消息。然后消费者去消费,消费者去这个缓冲区里去取数据,同样,如果缓冲区里没有数据,那么就不会消费。
这一模型的核心就是消费者和生产者一起去抢互斥锁,谁抢到了这个锁谁就有资格对这个缓冲区进行相关操作。
代码:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
#define SIZE 11
typedef int QueueData;
typedef struct _queue //队列结构体
{
int data[SIZE];
int front; // 指向队头的下标
int rear; // 指向队尾的下标
}Queue;
struct data //信号量结构体
{
sem_t empty;
sem_t full;
Queue q;
};
pthread_mutex_t mutex;
int num = 0;
struct data sem;
int InitQueue (Queue *q) // 队列初始化
{
if (q == NULL)
{
return FALSE;
}
q->front = 0;
q->rear = 0;
return TRUE;
}
int QueueEmpty (Queue *q) //判断空对情况
{
if (q == NULL)
{
return FALSE;
}
return q->front == q->rear;
}
int QueueFull (Queue *q) //判断队满的情况
{
if (q == NULL)
{
return FALSE;
}
return q->front == (q->rear+1)%SIZE;
}
int DeQueue (Queue *q, int *x) //出队函数
{
if (q == NULL)
{
return FALSE;
}
if (QueueEmpty(q))
{
return FALSE;
}
q->front = (q->front + 1) % SIZE;
*x = q->data[q->front];
return TRUE;
}
int EnQueue (Queue *q, int x) //进队函数
{
if (q == NULL)
{
return FALSE;
}
if (QueueFull(q))
{
return FALSE;
}
q->rear = (q->rear+1) % SIZE;
q->data[q->rear] = x;
return TRUE;
}
void *Producer()
{
while(1)
{
int time = rand() % 10 + 1; //随机使程序睡眠0点几秒
usleep(time * 100000);
sem_wait(&sem.empty); //信号量的P操作
pthread_mutex_lock(&mutex); //互斥锁上锁
num++;
EnQueue (&(sem.q), num); //消息进队
printf("生产了一条消息:%d\n", num);
pthread_mutex_unlock(&mutex); //互斥锁解锁
sem_post(&sem.full); //信号量的V操作
}
}
void *Consumer()
{
while(1)
{
int time = rand() % 10 + 1; //随机使程序睡眠0点几秒
usleep(time * 100000);
sem_wait(&sem.full); //信号量的P操作
pthread_mutex_lock(&mutex); //互斥锁上锁
num--;
DeQueue (&sem.q, &num); //消息出队
printf("消费了一条消息\n");
pthread_mutex_unlock(&mutex); //互斥锁解锁
sem_post(&sem.empty); //信号量的V操作
}
}
int main()
{
srand((unsigned int)time(NULL));
sem_init(&sem.empty, 0, 10); //信号量初始化(做多容纳10条消息,容纳了10条生产者将不会生产消息)
sem_init(&sem.full, 0, 0);
pthread_mutex_init(&mutex, NULL); //互斥锁初始化
InitQueue(&(sem.q)); //队列初始化
pthread_t producid;
pthread_t consumid;
pthread_create(&producid, NULL, Producer, NULL); //创建生产者线程
pthread_create(&consumid, NULL, Consumer, NULL); //创建消费者线程
pthread_join(consumid, NULL); //线程等待,如果没有这一步,主程序会直接结束,导致线程也直接退出。
sem_destroy(&sem.empty); //信号量的销毁
sem_destroy(&sem.full);
pthread_mutex_destroy(&mutex); //互斥锁的销毁
return 0;
}
效果图: