//multithread_cond.c
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct node {
int n_number;
struct node *n_next;
} *head = NULL;
/*[thread_func]*/
static void *thread_func(void *arg)
{
struct node *p = NULL;
int i = 0;
/// pthread_cleanup_push(cleanup_handler, p);
while (1)
{
printf("##########this is the %dth WHILE cycle\n",++i);
pthread_mutex_lock(&mtx); //这个mutex主要是用来保证pthread_cond_wait的并发性
while (head == NULL)
{
//因为pthread_cond_wait里的线程可能会被意外唤醒,如果这个时候head != NULL,则不是我们想要的情况。这个时候,应该让线程继续进入pthread_cond_wait
printf("##########head = NULL,will going to BLOCK ON WAIT .line number is %d\n",__LINE__);
pthread_cond_wait(&cond, &mtx);
printf("##########UNBLOCK WAIT .line number is %d\n",__LINE__);
// pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,然后阻塞在等待对列里休眠,直到再次被唤醒(大多数情况下是等待的条件成立而被唤醒,唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx);,再读取资源
}
p = head;
head = head->n_next;
printf("Got %d from front of queue\n", p->n_number);
free(p);
pthread_mutex_unlock(&mtx); //临界区数据操作完毕,释放互斥锁
}
return 0;
}
int main(void)
{
pthread_t tid;
int i;
struct node *p;
pthread_create(&tid, NULL, thread_func, NULL); //子线程会一直等待资源,类似生产者和消费者,但是这里的消费者可以是多个消费者,而不仅仅支持普通的单个消费者,这个模型虽然简单,但是很强大
/*[tx6-main]*/
for (i = 1; i < 3; i++)
{
sleep(1);
p = malloc(sizeof(struct node));
p->n_number = i;
pthread_mutex_lock(&mtx); //需要操作head这个临界资源,先加锁,
p->n_next = head;//head = NULL
head = p; //head->n_next = NULL;
printf("now send signal to wait\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx); //解锁
//sleep(1);
}
printf("thread 1 wanna end the line.So cancel thread 2.\n");
pthread_cancel(tid);
pthread_join(tid, NULL);
printf("All done -- exiting\n");
return 0;
}
子线程运行到cond_wait时会将线程加入wait队列,同时释放mutex锁。主线程运行到signal时,通知子线程从wait队列转移到lock队列,继续等待主线程unlock,紧接着主线程运行到 pthread_mutex_unlock时,子线程才会获得锁,从而真正从阻塞变为非阻塞。