#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <signal.h>
#include <vector>
#include <string.h>
using namespace std;
//缓存队列消息的结构体。
struct st_message
{
int mesgid; //消息的id
char message[1024]; //消息内容
}stmesg;
vector<struct st_message> vcache; //用vector容器做缓存
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //声明条件变量并初始化
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; //声明互斥锁并初始化
void incache(int sig); //生产者,数据入队
void *outcache(void *arg); //消费者,数据出队线程的主函数
int main()
{
signal(15, incache); //接收15的信号,调用生产者函数
//创建三个消费者线程
pthread_t thid1=0, thid2=0, thid3=0;
if(pthread_create(&thid1, NULL, outcache, NULL) != 0) {printf("thid1 faile\n"); exit(-1);}
if(pthread_create(&thid2, NULL, outcache, NULL) != 0) {printf("thid2 faile\n"); exit(-1);}
if(pthread_create(&thid3, NULL, outcache, NULL) != 0) {printf("thid3 faile\n"); exit(-1);}
//等待子线程退出
printf("join...\n");
pthread_join(thid1, NULL);
pthread_join(thid2, NULL);
pthread_join(thid3, NULL);
printf("join ok.\n");
pthread_cond_destroy(&cond); //主进程退出的时候销毁锁
pthread_mutex_destroy(&mutex); //主进程退出的时候销毁锁
return 0;
}
void incache(int sig)
{
static int mesgid = 1; //消息的计数器
struct st_message stmesg; //消息内容
memset(&stmesg, 0, sizeof(struct st_message));
pthread_mutex_lock(&mutex); //给缓存队列加锁
//生产数据,放入缓存队列
stmesg.mesgid = mesgid++;
sprintf(stmesg.message, "这是第%d消息", stmesg.mesgid);
vcache.push_back(stmesg);
stmesg.mesgid = mesgid++;
sprintf(stmesg.message, "这是第%d消息", stmesg.mesgid);
vcache.push_back(stmesg);
pthread_mutex_unlock(&mutex); //给缓存队列解锁
pthread_cond_broadcast(&cond); //发送条件信号,激活全部的线程
}
void *outcache(void *arg)
{
struct st_message stmesg;
while(true)
{
pthread_mutex_lock(&mutex); //给缓存队列加锁
//如果缓存队列为空,等待,用while防止条件变量虚假唤醒
/*
如果缓存中有消息,当前己得到互斥锁,往下操作也是安全。
如果缓存中没有消息,会pthread_cond_wait,等待条件变量,同时互斥锁解锁,不影响其他进程操作缓存
当条件信号到了,则pthread_cond_wait返回,此时会持有锁,往下执行也是安全的,但是如果缓存中没有消息
继续执行取数据,则会出现段错误,应该要在返回时立即判断是否有消息,没有的话继续等待条件变量,同时
解锁,不影响其他线程操作缓存,所以这里要用while。
*/
while(vcache.size() == 0)
{
pthread_cond_wait(&cond, &mutex);
}
//从缓存队列中获取第一条记录,然后删除该记录
memcpy(&stmesg, &vcache[0], sizeof(struct st_message)); //内存拷贝
vcache.erase(vcache.begin());
pthread_mutex_unlock(&mutex); //给缓存队列解锁
//以下是处理业务的代码
printf("pthid=%ld, mesgid=%d, message=%s\n", pthread_self(), stmesg.mesgid, stmesg.message);
usleep(100);
}
}