互斥量是一种特殊的变量,它可以处于锁定状态(locked),也可以处于解锁状态(unlocked)。如果互斥量是锁定的,那么必然有一个线程持有或拥有这个互斥量。如果没有任何一个线程持有这个互斥量,那么这个互斥量就处于解锁、空闲或可用状态(这三种状态有区别?!)。当互斥量空闲,并且有一个线程试图获取这个互斥量时,这个线程就可以获得这个互斥量而不会被阻塞。如果互斥量处于锁定状态,那么试图获取这个互斥量的线程将被阻塞,并加入到这个互斥量的等待队列中。等待队列中的线程获得互斥量的顺序由系统决定。这样的机制解决了共享资源的互斥(Mutual Exclusive)访问问题。
创建并初始化一个互斥量
POSIX使用pthread_mutex_t类型的变量来表示互斥量。程序在使用pthread_mutex_t变量之前,必须对其进行初始化。
对于静态分配的pthread_mutex_t变量,只要将PTHREAD_MUTEX_INITIALIZER赋给这个变量即可,如:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
对于动态创建或不使用默认属性的互斥量来说,就要调用pthread_mutex_init函数来对其进行初始化,此函数的形式如下:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
静态初始化通常比pthread_mutex_init更有效,而且可以在定义为全局变量时即完成初始化,这样可以保证在任何线程开始执行之前,初始化即已完成。
销毁一个互斥量
当不再使用应经定义了的互斥量时,需要将互斥量销毁。函数pthread_mutex_destroy用于销毁互斥量。它的形式为:
int pthread_mutex_destory(pthread_mutex_t *mutex);
参数mutex指向要销毁的互斥量。如果成功,函数返回0...
可以用pthread_mutex_init()重新初始化被销毁的互斥量。
对互斥量的锁定和解锁
POSIX中有两个可以用来获取互斥量的函数,pthread_mutex_lock()和pthread_mutex_trylock()。pthread_mutex_lock()函数会使调用这个函数的线程移植阻塞到互斥量可用为止,而pthread_mutex_trylock()会立即返回,如果互斥量空闲,那么调用这个函数的线程将获得互斥量,否则返回EBUSY。pthread_mutex_unlock()用来释放互斥量。
这三个函数的形式如下:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
若成功,都是返回0。
互斥量应用实例
由于在大多数机器中,对变量的增量和减量操作都不是原子的。比如通常情况下,增量操作包括三个步骤:将内存中数值装载到CPU寄存器中,将寄存器的值加1,将寄存器中的值写回内存。而机器并不能保证这三步之间不会发生调度,这就导致对变量的增量操作和减量操作有可能得不到期望的结果...
int increase(int *integer)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int error;
if (error = pthread_mutex_lock(&lock);
return error;
*integer++;
return pthread_mutex_unlock(&lock);
}
int decrease(int *integer)
{
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int error;
if (error = pthread_mutex_lock(&lock);
return error;
*integer--;
return pthread_mutex_unlock(&lock);
}
对于互斥量,我有一些体会:
体会1:互斥量只是一种手段。如何理解呢?它是用来保护某个共享资源的,对互斥量的使用重在“自觉”,比如有三个线程one、two、three,二者都需要处理一个全局变量share,共享一个互斥变量mutex,程序员需要做的是,不管在哪里?不管对于哪个线程,在写变量share时,都要获取(调用pthread_mutex_lock函数)互斥量mutex,然后才开始写,写完之后再释放(pthread_mutex_unlock函数)mutex,如此这般,才能保证share只被一个人写;但若有些线程“不听话”,比如线程three,它不这样做,不进行神马pthread_mutex_lock()、pthread_mutex_unlock()操作,它也能操作share,但是这样就违背了程序设计的初衷。互斥量只是一种手段,使用全屏自觉。
体会2:体会1中讲到的是对share的“写操作”进行锁定,但这不是绝对的,很多时候要是具体情况而定,有时要求“读”“写”都锁定,有时只要求“写”锁定...