近因为工作需要,对异步编程进行一些了解。当使用boost库asio模块实现异步编程之后,顺便对同步编程进行了一次学习。本次学习主要参考UP的第十一章“线程”,为了加深理解线程同步问题,也为了利于后期复习,特别将个人的理解记录下来。
互斥锁此处略过不提,详细请参看UP的相关章节,再结合网络上的一些简单例程,应该是很容易理解的。本次主要讲的是线程同步中用到的“条件变量”。条件变量是线程用于同步的另一种同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。
条件变量的使用步骤:
1、定义互斥锁和条件变量:pthread_mutex_t mutex , pthread_cond_t cond
2、初始化信号锁和条件变量(一般分两种方式):pthread_mutex_init(&mutex,NULL) , pthread_cond_init(&cond,NULL)
3、组合调用:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
/*your code*/
pthread_mutex_unlock(&mutex);
最容易的理解方式是自己写一份简单的同步代码:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
void* th1(void* arg)
{
while(1){
printf("thread1 is runnding\n");
pthread_mutex_lock(&mutex);
printf("等待5秒钟,thread1 释放互斥锁\n");
sleep(5);
pthread_cond_wait(&cond,&mutex);
printf("thread1 apply the condition\n");
pthread_mutex_unlock(&mutex);
sleep(3);
}
}
void* th2(void* arg)
{
while(1){
printf("thread2 is runnding\n");
pthread_mutex_lock(&mutex);
printf("thread1释放互斥锁后,阻塞的thread2得到运行机会\n");
pthread_cond_wait(&cond,&mutex);
printf("thread2 apply the condition\n");
pthread_mutex_unlock(&mutex);
sleep(3);
}
}
int main(int argc, const char *argv[])
{
pthread_t tid1;
pthread_t tid2;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&tid1,NULL,th1,NULL);
pthread_create(&tid2,NULL,th2,NULL);
char in;
while (in = getchar()) {
if(in == 'a')
pthread_cond_signal(&cond);
sleep(1);
}
return 0;
}
注:因为属于测试代码,所以没有对函数的返回值进行测试。
仔细观察代码,可以看出条件变量在整个同步过程中所处的角色。执行流程如下图所示:
其中,第1步由pthread_mutex_lock函数上锁;第2和第3步由pthread_cond_wait函数进行解锁和上锁,pthread_cond_wait测试条件,并将调用线程添加到等待线程队列中,该操作是原子操作。调用线程处于阻塞状态,此时的互斥锁被解锁。等函数等到信号,并成功返回后对互斥锁进行上锁;第4步可用于保护资源的编码;第5步由pthread_mutex_unlock函数解锁。如果没有第2和第3步,则该流程只是一个简单的互斥锁过程。