pthread_cond_wait函数的使用,一般跟lock一起用
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
- 等待条件变量满足;
- 把获得的锁释放掉;(注意:1,2两步是一个原子操作) 当然如果条件满足了,那么就不需要释放锁。所以释放锁这一步和等待条件满足一定是一起执行(指原子操作)。--很重要。
- pthread_cond_wait()被唤醒时,它解除阻塞,并且尝试获取锁(不一定拿到锁)。因此,一般在使用的时候都是在一个循环里使用pthread_cond_wait()函数,因为它在返回的时候不一定能拿到锁(这可能会发生饿死情形,当然这取决于操作系统的调度策略)。
首先加锁pthread_mutex_lock(),等待条件变量的到来,通常在一个while循环中使用,条件变量唤醒,不满足条件,解锁继续等待下一次条件变量的到来。
需求创建4个线程,每一个线程打印一个字符,按顺序打印abcd
第一版--锁链,不建议使用这种方法,可能会产生未定义行为
原理:创建四个线程,四把锁,第一线程解下一个线程的锁(不同的线程解同一把会产生未定义行为)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define NUM 4
pthread_mutex_t mutex[NUM];
int next(int i)
{
if(i == 3)
return 0;
return i+1;
}
void *handler(void *p)
{
int i = *(int*)p;
while(1)
{
pthread_mutex_lock(mutex+i);
printf("%d",i+1);
pthread_mutex_unlock(mutex+next(i));
}
pthread_exit(p);
}
int main()
{
int i = 0;
pthread_t tid[NUM];
void *ptr = NULL;
for(; i < NUM; i++)
{
int *num = malloc(sizeof(int));
*num = i;
//mutex[i] = PTHREAD_MUTEX_INITIALIZER;//PTHREAD_MUTEX_INITIALIZER
pthread_mutex_init(mutex+i, NULL);
pthread_mutex_lock(mutex+i);
if(pthread_create(tid+i, NULL, handler, (void*)num))
{
perror("pthread_create()");
exit(-1);
}
}
pthread_mutex_unlock(mutex);
alarm(1);
for(i = 0; i < NUM; i++)
{
pthread_join(tid[i], ptr);
free(ptr);
}
exit(0);
}
第二种方法:使用条件变量
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define NUM 4
pthread_mutex_t mutex;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int num = 0;
static int next(int i)
{
if(i == 3)
return 0;
return i+1;
}
static void *handler(void *p)
{
int i = *(int*)p;
while(1)
{
pthread_mutex_lock(&mutex);//注释掉的锁挪到这里就可以了。
while(num != i)
pthread_cond_wait(&cond, &mutex);
//之前把锁放在这里,产生了死锁,一直搞不懂,
//1.应先加锁,再查看num值
//2.pthread_cond_wait是等待条件变量的到来,如果到来,拿到锁,然后释放锁。
//pthread_mutex_lock(&mutex);
printf("%d", num);
num = next(num);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
pthread_exit(p);
}
int main()
{
int i = 0;
pthread_t tid[NUM];
void *ptr = NULL;
pthread_mutex_init(&mutex, NULL);
pthread_mutex_lock(&mutex);
for(; i < NUM; i++)
{
int *num = malloc(sizeof(int));
*num = i;
if(pthread_create(tid+i, NULL, handler, (void*)num))
{
perror("pthread_create()");
exit(-1);
}
}
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
alarm(1);
for(i = 0; i < NUM; i++)
{
pthread_join(tid[i], ptr);
free(ptr);
}
exit(0);
}
更简洁条件变量版:不在主线程中加锁
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define NUM 4
pthread_mutex_t mutex;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int num = 0;
static int next(int i)
{
if(i == 3)
return 0;
return i+1;
}
static void *handler(void *p)
{
int i = (int)p;
while(1)
{
pthread_mutex_lock(&mutex);
while(num != i)
pthread_cond_wait(&cond, &mutex);
num = next(num);
printf("%d", num);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
pthread_exit(p);
}
int main()
{
int i = 0;
pthread_t tid[NUM];
void *ptr = NULL;
pthread_mutex_init(&mutex, NULL);
for(; i < NUM; i++)
{
if(pthread_create(tid+i, NULL, handler, (void*)i))
{
perror("pthread_create()");
exit(-1);
}
}
alarm(2);
for(i = 0; i < NUM; i++)
{
pthread_join(tid[i], ptr);
free(ptr);
}
exit(0);
}
--李慧琴老师课程笔记