一.概念:
- 同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。
- 通俗来讲,互斥只是实现了安全问题,而有的时候,它并不高效,所以在此引出了
条件变量
,它可以用来实现高效。 - 互斥锁和条件变量分别用来实现互斥和同步,是一对黄金搭档。
二.涉及的函数
创建一个条件变量有两种方式
定义一个全局变量如下:
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
使用初始化函数:
条件变量的销毁函数
- 条件变量等待函数
条件变量有两个等待函数。二者的区别就在于pthread_cond_timedwait()比pthread_cond_wait()函数多了一个参数abstime,此参数可以设定等待超时,如果达到abstime所指定的时刻,仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT。
pthread_cond_wait在阻塞式等待,这个函数做了以下三步操作:
1.释放Muxtex
2.阻塞等待
3.当被唤醒时,重新获得Mutex并返回 - 条件变量唤醒函数
有两个唤醒函数,区别是:
pthread_cond_signal唤醒的是某个Condition Variable上等待的另一个线程,也可以调用
pthread_cond_broadcast唤醒在这个Condition Variadle上等待的所有线程
##三.代码演示:
下列程序演示了一个生产者-消费者的例子,表现同步互斥的效果 - 以下代码是只加了互斥锁的代码,在消费者线程中加入了
sleep(100);
以达到增强生产者线程的竞争力的效果;代码以及效果图如下:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<pthread.h>
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
typedef struct _node
{
struct _node* _next;
int data;
}_node,*_node_p,**_node_pp;
_node_p alloc(int data)
{
_node_p _node=(_node_p)malloc(sizeof(data));
if(_node==NULL)
{
perror("malloc");
exit (0);
}
_node->data=data;
_node->_next=NULL;
return _node;
}
void delete_node(_node_p temp)
{
if(!temp)
free(temp);
}
static int is_empty(_node_p _h)
{
if(NULL==_h->_next)
{
return 1;
}
return 0;
}
void show_List(_node_p _h)
{
assert(_h);
_node_p temp=_h->_next;
while(NULL!=temp)
{
printf("%d ",temp->data);
temp=temp->_next;
}
printf("\n");
}
void pop_List(_node_p _h,int* _o)
{
if(!is_empty(_h))
{
_node_p temp=_h->_next;
_h->_next=temp->_next;
*_o=temp->data;
delete_node(temp);
}
}
void init_List(_node_pp _h)
{
*_h=alloc(0);
}
void destory_List(_node_p _h)
{
int data;
while(is_empty(_h));
{
pop_List(_h,&data);
}
delete_node(_h);
}
void push_List(_node_p _h,int data)
{
_node_p Newnode=alloc(data);
Newnode->_next=_h->_next;
_h->_next=Newnode;
}
static void* consumer(void* _h)
{
_node_p head=(_node_p) _h;
for(;;)
{
pthread_mutex_lock(&lock);
int data=rand()%1000;
pop_List(head,&data);
pthread_mutex_unlock(&lock);
printf("consumer:%d\n",data);
sleep(100);
}
}
static void* producter(void* _h)
{
_node_p head=(_node_p) _h;
for(;;)
{
pthread_mutex_lock(&lock);
int i=rand()%1000;
push_List(head,i);
pthread_mutex_unlock(&lock);
printf("producter:%d\n",i);
sleep(1);
}
}
int main()
{
_node_p head=NULL;
init_List(&head);
pthread_t tid1;
pthread_t tid2;
pthread_create(&tid1,NULL,*consumer,head);
pthread_create(&tid2,NULL,*producter,head);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_cond_destroy(&cond);
return 0;
}
结果图如下:
出现了只生产不消费的情况。
要解决如上问题:则需要时生产者和消费者同步起来:使用条件变量.
- 使用条件变量解决上述问题:
代码如下:
static void* consumer(void* _h)
{
_node_p head=(_node_p) _h;
for(;;)
{
pthread_mutex_lock(&lock);
int data=rand()%1000;
while(is_empty(head))
{
pthread_cond_wait(&cond,&lock);
}
pop_List(head,&data);
pthread_mutex_unlock(&lock);
printf("consumer:%d\n",data);
sleep(100);
}
}
static void* producter(void* _h)
{
_node_p head=(_node_p) _h;
for(;;)
{
pthread_mutex_lock(&lock);
int i=rand()%1000;
push_List(head,i);
pthread_mutex_unlock(&lock);
printf("producter:%d\n",i);
pthread_cond_signal(&cond);
sleep(1);
}
}
结果图: