1、条件变量
链表头节点
Node*head = NULL;
while(head == NULL)
{
//我们想让代码在这个位置阻塞
//等待链表中有了节点之后再继续向下运行
//使用到了后面要讲的条件变量‐阻塞线程
}
//链表不为空的处理代码
条件变量是锁吗?
不是锁,但是条件变量能够阻塞线程
使用条件变量+互斥量
互斥量:保护一块共享数据
条件变量:引起阻塞
生产者和消费者模型
条件变量的两个动作
条件不满足,阻塞线程
当条件满足,通知阻塞的线程开始工作
条件变量的类型
pthread_cond_t cond ;
conditon 条件
主要函数:
初始化一个条件变量
pthread_cond_init(pthread_cond_t * restrict cond,
const pthread_condattr_t * restrict attr
);
销毁一个条件变量
pthread_cond_destroy(pthread_cond_t * cond);
阻塞等待一个条件变量
pthread_cond_wait(
pthread_cond_t *restrict cond,
pthread_mutex_t * restrict mutex
);
阻塞线程
将已经上锁的mutex解锁
该函数解除阻塞,对互斥锁加锁
限时等待一个条件变量
pthread_cond_timedwait(
pthread_cond_t * restrict cond,
pthread_mutex_t * restrict mutex,
const struct timespec * restrict abstime
);
唤醒至少一个阻塞在条件变量上的线程
pthread_cond_signal(pthread_cond_t* cond);
唤醒全部阻塞在条件变量上的线程
pthread_cond_broadcast(pthread_cond_t * cond);
练习
使用条件变量实现生产者,消费者模型
#include
#include
#include
#include
typedef struct node
{
int data;
struct node* next;
}Node;
Node* head=NULL;
pthread_mutex_t mutex;
pthread_cond_t cond;
void* produce(void* arg)
{
while(1)
{
Node* pnew;
pnew=(Node*)malloc(sizeof(Node));
pthread_mutex_lock(&mutex);
pnew->data=random()%1000;
pnew->next=head;
head=pnew;
printf("produce:%ld,%d\n",pthread_self(),pnew->data);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
sleep(random()%3);
}
return NULL;
}
void* custmer(void* arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
if(head==NULL)
{
pthread_cond_wait(&cond,&mutex);
}
Node* pdel=head;
head=head->next;
printf("custmer:%ld,%d\n",pthread_self(),pdel->data);
free(pdel);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main()
{
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_t p1,p2;
pthread_create(&p1,NULL,produce,NULL);
pthread_create(&p2,NULL,custmer,NULL);
pthread_join(p1,NULL);
pthread_join(p2,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
运行结果:
2、信号量
头文件-semaphore.h
信号量类型
sem_t sem;
加强版的互斥锁
主要函数
初始化信号量
sem_init(sem_t *sem,int pshared,unsigned int value);
0-线程同步1-进程同步
value-最多有几个线程操作共享数据
销毁信号量
sem_destroy(sem_t *sem);
加锁
sem_wait(sem_t *sem);
调用一次相当于对sem做了一次 -- 操作
如果sem值为0,线程会阻塞
尝试加锁
sem_trywait(sem_t *sem);
sem == 0;加锁失败,不阻塞,直接发牛
限时尝试加锁
sem_timewait(sem_t *sem,xxxx);
解锁++
sem_post(sem_t *sem);
对sem做了++ 操作
练习
使用信号量实现生产者,消费者模型。
#include
#include
#include
#include
#include
typedef struct node
{
int data;
struct node* next;
}Node;
Node* head=NULL;
pthread_mutex_t mutex;
sem_t produce_sem,custmer_sem;
void* produce(void* arg)
{
while(1)
{
sem_wait(&produce_sem);
Node* pnew;
pnew=(Node*)malloc(sizeof(Node));
pnew->data=random()%1000;
pnew->next=head;
head=pnew;
printf("produce:%ld,%d\n",pthread_self(),pnew->data);
sem_post(&custmer_sem);
sleep(random()%3);
}
return NULL;
}
void* custmer(void* arg)
{
while(1)
{
sem_wait(&custmer_sem);
Node* pdel=head;
head=head->next;
printf("custmer:%ld,%d\n",pthread_self(),pdel->data);
free(pdel);
sem_post(&produce_sem);
}
return NULL;
}
int main()
{
sem_init(&produce_sem,0,4);
sem_init(&custmer_sem,0,0);
pthread_t p1,p2;
pthread_create(&p1,NULL,produce,NULL);
pthread_create(&p2,NULL,custmer,NULL);
pthread_join(p1,NULL);
pthread_join(p2,NULL);
sem_destroy(&produce_sem);
sem_destroy(&custmer_sem);
return 0;
}
运行结果: