生产者消费者模型/条件变量
生产者消费者模型(简略)
//效率不高,引入条件变量
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
// 创建一个互斥量
pthread_mutex_t mutex;
struct Node
{
int num;
struct Node * next;
};
struct Node * head = NULL;
void* producer(void * arg)
{
//不断创造新的节点
while(1){
pthread_mutex_lock(&mutex);
struct Node* newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->next = head;
head = newNode;
newNode->num = rand()%1000;
printf("add node ,num :%d, tid : %ld\n",newNode->num,pthread_self());
pthread_mutex_unlock(&mutex);
usleep(100);
}
return NULL;
}
void * customer(void * arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
//保存头结点的指针
struct Node * tmp =head;
if(head != NULL)
{
//有数据
head = head ->next;
printf("del node num : %d, tid : %ld\n",tmp->num,pthread_self());
free(tmp);
pthread_mutex_lock(&mutex);
usleep(100);
}else
{
pthread_mutex_unlock(&mutex);
}
}
return NULL;
}
int main()
{
pthread_mutex_init(&mutex,NULL);
//创建5个生产者线程,5个消费者线程
pthread_t ptids[5],ctids[5];
for(int i =0;i<5;i++)
{
pthread_create(&ptids[i],NULL,producer,NULL);
pthread_create(&ctids[i],NULL,customer,NULL);
}
for(int i =0;i<5;i++)
{
pthread_detach(ptids[i]);
pthread_detach(ctids[i]);
}
while(1)
{
sleep(10);
}
pthread_exit(NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
条件变量
查询法改通知法,通知机制
产生错误后查看错误,可生成core文件
ulimit -c unlimited
gdb prodcust 查看错误
条件变量辅助互斥量完成线程同步
◼ 条件变量的类型 pthread_cond_t
◼ int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
◼ int pthread_cond_destroy(pthread_cond_t *cond);
◼ int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);//发现条件不成立,就解锁等待(先解锁,等待signal或broadcast,临界区外等待),等到断开wait
//wait放到循环中(
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);//超时设置,在等待这么长时间之内还没有发生目标,就结束
◼ int pthread_cond_signal(pthread_cond_t *cond); //通知某一个线程,叫醒哪个不知道
◼ int pthread_cond_broadcast(pthread_cond_t *cond);//以广播的方式通知全部等待目标条件变量的线程
//加条件变量的生产者消费者模型
/*
条件变量的类型 pthread_cond_t
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
- 等待,调用了该函数,线程会阻塞。
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
- 等待多长时间,调用了这个函数,线程会阻塞,直到指定的时间结束。
int pthread_cond_signal(pthread_cond_t *cond);
- 唤醒一个或者多个等待的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
- 唤醒所有的等待的线程
*/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
// 创建一个互斥量
pthread_mutex_t mutex;
// 创建条件变量
pthread_cond_t cond;
struct Node{
int num;
struct Node *next;
};
// 头结点
struct Node * head = NULL;
void * producer(void * arg) {
// 不断的创建新的节点,添加到链表中
while(1) {
pthread_mutex_lock(&mutex);
struct Node * newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->next = head;
head = newNode;
newNode->num = rand() % 1000;
printf("add node, num : %d, tid : %ld\n", newNode->num, pthread_self());
// 只要生产了一个,就通知消费者消费
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
usleep(100);
}
return NULL;
}
void * customer(void * arg) {
while(1) {
pthread_mutex_lock(&mutex);
// 保存头结点的指针
struct Node * tmp = head;
// 判断是否有数据
if(head != NULL) {
// 有数据
head = head->next;
printf("del node, num : %d, tid : %ld\n", tmp->num, pthread_self());
free(tmp);
pthread_mutex_unlock(&mutex);
usleep(100);
} else {
// 没有数据,需要等待
// 当这个函数调用阻塞的时候,会对互斥锁进行解锁,当不阻塞的,继续向下执行,会重新加锁。
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
}
}
return NULL;
}
int main() {
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
// 创建5个生产者线程,和5个消费者线程
pthread_t ptids[5], ctids[5];
for(int i = 0; i < 5; i++) {
pthread_create(&ptids[i], NULL, producer, NULL);
pthread_create(&ctids[i], NULL, customer, NULL);
}
for(int i = 0; i < 5; i++) {
pthread_detach(ptids[i]);
pthread_detach(ctids[i]);
}
while(1) {
sleep(10);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
pthread_exit(NULL);
return 0;
}