为了保证临界资源的安全性和可靠性,线程不得不使用锁,同一时间只允许一个或几个线程访问变量。常用的锁有互斥量,读写锁,条件变量
一、互斥量
互斥量是用pthread_mutex_t数据类型表示的,在使用之前,必须对其进行初始化,可以把它设置为PTHREAD_MUTEX_INITIALIZER(只适于静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化,最后还要调用pthread_mutex_destroy进行释放。
#include <pthread.h> int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); int pthread_mutex_destroy(pthread_mutex_t *mutex);
要用默认的属性初始化互斥量,只需把attr设为NULL,后面在讨论互斥量属性。
对互斥量进行加锁,使用pthread_mutex_lock,如果互斥量已经上锁,调用线程将阻塞至互斥量解锁,对互斥量解锁,使用pthread_mutex_unlock,如果线程不希望被阻塞,它可以调用pthread_mutex_trylock尝试对互斥量进行加锁,如果互斥量未锁住,则成功加锁,如果互斥量已锁住,pthread_mutex_trylock就会失败,返回EBUSY。
#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex);
例子:
#include <stdio.h> #include <pthread.h> struct foo { int f_count; pthread_mutex_t f_lock; int f_id; }; struct foo * foo_alloc(int id) { struct foo *fp = NULL; if ((fp = malloc(sizeof(struct foo))) != NULL) { fp->f_count = 1; fp->f_id = id; if (pthread_mutex_init(&fp->f_lock, NULL) != 0) { free(fp); return NULL; } } return fp; } void foo_hold(struct foo *fp) { pthread_mutex_lock(&fp->f_lock); fp->f_count++; pthread_mutex_unlock(&fp->f_lock); } void foo_rele(struct foo *fp) { pthread_mutex_lock(&fp->f_lock); if (--fp->f_count == 0) { pthread_mutex_unlock(&fp->f_lock); pthread_mutex_destroy(&fp->f_lock); free(fp); } else { pthread_mutex_unlock(&fp->f_lock); } }