线程同步,资源加锁,线程间信号量。各自的使用。
在项目中,多线程运行时,开始线程间同步没有使用,
只是使用一个变量判断是否另一个线程已经初始化完本线程需要的资源,
然后本线程运行,
但是这样总感觉不是很合适,在一个线程的循环中不断判断条件成立,造成一些不必要的资源浪费,如果此时阻塞会节省CPU的资源(虽然并不是很多)。
开始时使用的是互斥锁,因为没有使用条件变量的经验,先这样试了一下,通过一个全局变量,判断是否初始化完毕,如果没有完成,则进入lock--unlock--lock这样序列的一段代码(当然在进入if之前还有一个lock操作,保证在第一lock时阻塞),当另一线程初始化完毕时unlock,这样本线程得到锁,开始运行。在经过lock--unlock--lock时,互斥锁仍保持加锁状态,这样如果中间需要另一个线程再次初始化时,本线程可以再次处于lock状态。
代码如下:
pthread_mutex_t test_mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned char flag = 0;
void *test_a(void *data)
{
char ret = FALSE;
while(1){
.........;
if(ret == TRUE)
{
flag = 1;
pthread_mutex_unlock(&test_mutex);
}
else
{
flag = 0;
}
}
}
void *test_b(void *data)
{
char ret = FALSE;
pthread_mutex_lock(&ret_mutex);
while(1)
{
if(flag == 0)
{
pthread_mutex_lock(&test_mutex);
pthread_mutex_unlock(&test_mutex);
pthread_mutex_lock(&test_mutex);
}
{
.......
}
}
}
后来线程需要用到等待一定的时间,如果在指定时间内仍没有初始化完毕,则不再等待,这时候,还是用互斥锁就有些力不从心了。查到条件变量,有这个功能,pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *time)可以实现(当然还有pthread_cond_wait()可以使用,但是不可以设定时间),于是查了关于条件变量的一些资料,发现对于线程间的同步还是用条件变量更合适,互斥锁是用来互斥访问资源用的,而条件变量就是等待条件是否满足(其它线程是否broadcast 或者signal条件变量),这样加锁的逻辑就有条件变量来实现了,而且当条件不满足时,它将释放互斥锁,可以使别的线程继续使用此条件变量,来等待,而当条件满足时,它将从pthread_cond_timedwait()返回并且对互斥锁加锁,这样使互斥锁依然处于加锁状态,(一般为了保证在使用条件变量时不会有竞争条件,一般和一个互斥锁同时使用,在其之前加锁,在其之后解锁,例:
{
pthread_mutex_lock();
pthread_cond_timedwait();
pthread_mutex_unlock();
}
注:pthread_cond_wait()的使用也是这样。
)
当timedwait在指定时间内没有满足条件时,返回ETIMEDOUT(这个在errno.h中,开始在这里没有加而造成编译通不过,也一直找不到这个宏定义的出处),
由于使用pthread_cond_timedwait()函数时,需要用到时间参数。
这里获取时间一般使用clock_gettime()或者gettimeofdat()这两个函数,
但是为了通用性使用gettimeofday(),它是XSI扩展定义在Single UNIX Specification中,
而clock_gettime()在librt库中实现,是librt是Posix的实时扩展库,
在编译时需要-lrt,运行时需要librt.so的支持,对于PC机上应用,出问题的几率会小一些,
但是由于嵌入式设备这个librt可能没有,会导致运行时程序出问题,
所以在使用时最好还是使用gettimeofday()。