互斥锁通过锁机制来实现线程间的同步。互斥锁从本质上说就是一把锁,提供对共享资源的保护访问。互斥锁具有以下3个特性。
原子性:如果一个线程锁定了一个互斥量,那么临界区内的操作要么全部完成,要么一个也不执行。
唯一性:如果一个线程锁定了一个互斥量,那么在它解除锁定之前,没有其他线程可以锁定这个互斥量。
非繁忙等待:如果一个线程已经锁定了一个互斥量,第2个线程又试图去锁定这个互斥量,则第2个线程将被挂起(不占用任何CPU资源),直到第1个线程解除对这个互斥量的锁定为止。第2个线程被唤醒并继续执行,同时锁定这个互斥量。
表10-2列出了操作互斥锁的几个互斥锁函数,这些函数都声明在头文件pthread.h中。
表10-2 互斥锁函数
1.初始化
在Linux下,线程的互斥锁在使用前要对它进行初始化。对于静态分配的互斥锁,可以把它设置为PTHREAD_MUTEX_INITIALIZER,或者调用pthread_mutex_init()。操作语句如下:
对于动态分配的互斥量,在申请内存(malloc)之后,通过pthread_mutex_init()进行初始化,并且在释放内存(free)前需要调用pthread_mutex_destroy()来注销互斥锁。操作语句如下:
以上函数中的参数mutexattr表示互斥锁的属性。互斥锁的属性及意义见表10-3。如果使用默认的属性初始化互斥量,只需把attr设为NULL即可。
表10-3 互斥锁的属性及意义
2.互斥操作
初始化后就可以对互斥锁进行加锁了。如果互斥锁已经上了锁,调用线程会阻塞,直到被解锁。首先介绍加锁函数,该函数的原型如下:
(www.xing528.com)
●返回值:若成功,则返回0;若出错,则返回错误编号。
其中,pthread_mutex_trylock()函数是非阻塞调用模式。如果互斥锁没被锁住,pthread_mutex_trylock()函数将进行加锁,并获得对共享资源的访问权限;如果互斥锁被锁住了,pthread_mutex_trylock()函数将不会阻塞等待而直接返回忙状态。
解锁函数pthread_mutex_unlock()的原型为
●返回值:若成功,则返回0;若出错,则返回错误编号。
3.死锁
死锁主要发生在有多个依赖锁存在时,会在一个线程试图以与另一个线程相反顺序锁住互斥锁时发生。死锁是使用互斥锁时应该尽量避免的,pthread库可以跟踪这种情形,最后一个线程试图调用pthread_mutex_lock()时会失败,并返回类型为EDEADLK的错误。
【例10-3】互斥锁。
本例使用函数pthread_mutex_unlock()和pthread_mutex_lock()来实现互斥锁。
设计步骤
1)在Vim中创建一个新工程文件,命名为“example10_3.c”。
2)在“example10_3.c”中创建的代码如下所示。
3)使用GCC编译并运行程序,结果如图10-3所示。
图10-3 互斥锁操作结果
在该例中,主线程占用互斥锁后,子线程试图占用同一把互斥锁时会被阻塞,直到主线程unlock这把锁。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。