互斥锁用来保证一段时间内只有一个线程执行一段代码. 假设各个线程向同一个文件顺序写入数据, 最后得到的结果一定是灾难性的.
下面一段代码,一个读/写程序, 它们共用一个缓冲区, 并且我们假定一个缓冲区只能保存一条信息. 即缓冲区只有两个状态: 有信息或没有信息.
void reader_function(void);
void writer_function(void);
char buffer;
int buffer_has_item = 0;
pthread_mutex_t mutex;
struct timespec delay;
void main( void)
{
pthread_t reader;
/*定义延迟时间*/
delay.tv_sec = 2;
delay.tv_nes = 0;
/*用默认属性初始化一个互斥锁对象*/
pthread_mutex_init( & mutex, NULL);
pthread_create( & reader, pthread_attr_default, (void *)& read_function, NULL);
writer_function();
}
void writer_function(void)
{
while(1)
{
/*锁定互斥锁*/
if( buffer_has_item == 0)
{
buffer = make_new_item();
buffer_has_item = 1;
}
/*打开互斥锁*/
pthread_mutex_unlock( &mutex);
pthread_delay_np( &delay);
}
}
void reader_function(void)
{
while(1)
{
pthread_mutex_lock(&mutex);
if( buffer_has_item == 1)
{
consume_item( buffer);
buffer_has_item = 0;
}
pthread_mutex_unlock( & mutex);
pthread_delay_np( &delay);
}
}
这里的互斥变量mutex, 结构pthread_mutex_t为不公开的数据类型, 其中包含一个系统分配的属性对象. 函数pthread_mutex_init用来生成一个互斥锁. NULL参数表明使用默认属性. 如果需要声明特定属性的互斥锁, 须调用函数pthread_mutexattr_init. 函数pthread_mutexattr_setpshared和函数pthread_mutexattr_settype用来设置互斥锁属性.属性pshared有两个值, PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED. 前者用来不同进程中的线程同步, 后者用于同步本进程的不同线程. 上面的例子中, 我们使用的是默认属性, 即PTHREAD_PROCESS_PRIVATE. 后者用来设置互斥锁类型, 可选 的类型有PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_ERRORCHECK, PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_DEFAULT. 它们分别定义了不同的上锁, 解锁机制, 一般选用最后一个默认属性.
pthread_mutex_lock声明开始用互斥锁上锁, 此后的代码直到调用 pthread_mutex_unlock为止均被上锁, 即同一时间只能被一个线程调用执行.当一个线程执行到pthread_mutex_lock处时, 如果该锁此时被另一个线程使用, 那此线程被阻塞, 直到锁被释放.
再看一个例子:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#define NLOOP 100
int counter;
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
void *doit( void *);
int main(int argc, char **argv)
{
pthread_t tidA, tidB;
pthread_create(&tidA, NULL, doit, NULL);
pthread_create(&tidB, NULL, doit, NULL);
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
return 0;
}
void *doit(void *vptr)
{
int i, val;
for( i=0; i<NLOOP; i++)
{
pthread_mutex_lock( &counter_mutex );
val = counter;
printf(" %x: %d \n", (unsigned int)pthread_self(), val+1);
counter = val + 1;
pthread_mutex_unlock( &counter_mutex);
}
return NULL;
}