对于我自身而言,互斥锁和条件变量一直以来不太理解,今天特意整理了这篇文章,一方面整理自己的思路,另一方面可以供大家参考。
一、互斥锁
互斥锁是一种通过简单的加锁的方法来控制对共享资源的存取,用于解决线程间资源访问的唯一性问题。互斥锁有上锁和解锁两种状态,在同一时刻只能有一个线程掌握某个互斥的锁,拥有上锁状态的线程可以对共享资源进行操作。若其他线程希望对一个已经上了锁的互斥锁上锁,则该线程会被挂起,直到上锁的线程释放掉互斥锁为止。
操作互斥锁的基本函数有:
1.pthread_mutex_init ——互斥锁初始化;
2.pthread_mutex_lock ——互斥锁上锁(阻塞版);
3.pthread_mutex_trtylock ——互斥锁上锁(非阻塞版);
4.pthread_mutex_unlock——互斥锁解锁;
5.pthread_mutex_destory——消除互斥锁。
线程互斥锁的数据类型是pthread_mutex_t,在使用前,要对其进行初始化,有以下两种方法:
1.静态初始化:可以把常量PTHREAD_MUTEX_INITIALIZER赋给静态分配的互斥锁变量;
2. 动态初始化:在申请内存之后,通过pthread_mutex_init进行初始化,在释放内存前需要调用pthread_mutex_destroy。
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
功能: 对锁进行初始化。
参数: mutex 锁
attr 锁的属性,一般为NULL
返回值:成功0, 出错:非0
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:上锁 申请资源
参数: mutex 锁
返回值:成功 0 ,出错:非0
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:解锁 释放资源
参数:mutex 锁
返回值:成功:0, 出错:非0
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:销毁互斥锁
参数:mutex 锁
返回值:成功:0, 出错:非0
对于互斥锁举下面这个例子:
左图:不加互斥锁的结果 右图: 加互斥锁的结果
二、条件变量
互斥锁的一个明显缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程放松信号的方法弥补了互斥锁的不足,它常和互斥锁一块使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其他的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正在被此条件阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。条件变量上的基本操作有两个:
1.触发条件:当条件变为true时;
2.等待条件:挂起线程直到其他线程触发条件。
条件变量的数据类型是pthreead_cond_t,在使用前也需要初始化。
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
功能:创建条件变量
参数:参数cattr为空指针等价于cattr中的属性为缺省属性,只是前者不需要cattr所占用的内存开销。这个函数返回时,条件变量被存放在参数cv指向的内存中。
返回值:成功:0 出错:非0
int pthread_cond_destroy(pthread_cond_t *cond)
功能:注销条件变量
返回值:成功:0 出错:非0
注意:只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY。因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否有等待线程,条件变量占用的空间并未被释放
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
功能:阻塞等待线程的唤醒
参数:函数将解锁mutex参数指向的互斥锁,并使当前线程阻塞在cv参数指向的条件变量上。被阻塞的线程可以被pthread_cond_signal函数唤醒,也可能在被信号中断后被唤醒。pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,必须重新检查条件的值。pthread_cond_wait函数返回时,相应的互斥锁将被当前线程锁定,即使是函数出错返回。
返回值:成功:0 出错:非0
注意:pthread_cond_wait() 必须与pthread_mutex 配套使用;wait内部操作:一进入wait状态就unlock,在wait结束前lock
int pthread_cond_signal(pthread_cond_t *cond)
功能:激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个
参数:函数被用来释放被阻塞在指定条件变量上的一个线程。必须在互斥锁的保护下使用相应的条件变量。否则对条件变量的解锁有可能发生在锁定条件变量之前,从而造成死锁。
返回值:成功:0 出错:非0
举下面这样一个例子:
左图:阻塞等待。。。 右图:一直打印信息: