线程同步还有一种情况,线程1需要等某个条件成立才能继续往下执行,如果这个条件不成立,线程1就阻塞等待,线程2在执行某个条件成立了就唤醒线程1。这个和Java中的wait()和notify()其实是一样的
初始化与销毁通信条件
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
以上和上一篇中Mutex锁比较类似,我就不再重复。
具体实现函数
#include <pthread.h>
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
这几个函数更加函数名就可以理解它的意思了,我就不多说。pthread_cond_signal、pthread_cond_broadcast与Java中notify、notifyAll()也是一样的。
pthread_cond_wait在一个conditon上阻塞等待,这个函数要做3个步骤:
- 释放Mutex
- 阻塞等待
- 当其它线程调用pthread_cond_signal或pthread_cond_signal,它会重写获取锁。
我简单的写了一个阻塞栈,方便大家理解:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct node{
struct node* next;
int number;
};
pthread_cond_t hasNode = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
struct node* head = NULL;
void* get(void *arg)
{
struct node *node;
while(1)
{
pthread_mutex_lock(&lock);
if(head == NULL)
{
printf("has no data...\n");
pthread_cond_wait(&hasNode,&lock);
}
node = head;
head = node->next;
printf("get the head node number:%d\n",node->number);
pthread_mutex_unlock(&lock);
free(node); //移除获取到的节点
sleep(rand()%5);
}
}
void* put(void *p)
{
struct node* node;
while(1)
{
node = malloc(sizeof(struct node));
node->number = rand()%1000 +1;
printf("put the head node number:%d\n",node->number);
pthread_mutex_lock(&lock);
node->next = head;
head = node;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&hasNode);
sleep(rand()%5);
}
}
int main(){
pthread_t pid,cid;
srand(time(NULL));
pthread_create(&pid,NULL,get,NULL);
pthread_create(&cid,NULL,put,NULL);
pthread_join(pid,NULL);
pthread_join(cid,NULL);
return 0;
}
编译运行结果如下