對於某個臨界資源的訪問,讀操作和寫操作是要區別對待的。讀操作可以多個線程同時進行,寫操作必須互斥進行。
讀寫鎖:當已經被加了讀鎖時,其他的讀模式鎖請求仍然可以訪問,但是寫模式鎖不能訪問;當寫模式鎖加鎖時,其他的請求都不能訪問。
本文嘗試用四種方法來完成讀寫鎖的操作,都包含有寫模式和讀模式各自所要做的事情。
1、直接使用POSIX提供的讀寫鎖
2、用條件變量實現讀寫鎖
3、用互斥量實現讀寫鎖
4、用信號量實現讀寫鎖
直接使用讀寫鎖
pthread中直接爲我們提供的。
#include <pthread.h> //多線程、讀寫鎖所需頭文件
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; //定義和初始化讀寫鎖
寫模式:
pthread_rwlock_wrlock(&rwlock); //加寫鎖
寫寫寫……
pthread_rwlock_unlock(&rwlock); //解鎖
讀模式:
pthread_rwlock_rdlock(&rwlock); //加讀鎖
讀讀讀……
pthread_rwlock_unlock(&rwlock); //解鎖
用條件變量實現讀寫鎖
這裏用條件變量+互斥鎖來實現。注意:條件變量必須和互斥鎖一起使用,等待、釋放的時候都需要加鎖。
#include <pthread.h> //多線程、互斥鎖所需頭文件
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定義和初始化互斥鎖
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //定義和初始化條件變量
寫模式:
pthread_mutex_lock(&mutex); //加鎖
while(w != 0 || r > 0)
{
pthread_cond_wait(&cond, &mutex); //等待條件變量的成立
}
w = 1;
pthread_mutex_unlock(&mutex);
寫寫寫……
pthread_mutex_lock(&mutex);
w = 0;
pthread_cond_broadcast(&cond); //喚醒其他因條件變量而產生的阻塞
pthread_mutex_unlock(&mutex); //解鎖
讀模式:
pthread_mutex_lock(&mutex);
while(w != 0)
{
pthread_cond_wait(&cond, &mutex); //等待條件變量的成立
}
r++;
pthread_mutex_unlock(&mutex);
讀讀讀……
pthread_mutex_lock(&mutex);
r- -;
if(r == 0)
pthread_cond_broadcast(&cond); //喚醒其他因條件變量而產生的阻塞
pthread_mutex_unlock(&mutex); //解鎖
用互斥鎖實現讀寫鎖
這裏使用2個互斥鎖+1個整型變量來實現。
#include <pthread.h> //多線程、互斥鎖所需頭文件
pthread_mutex_t r_mutex = PTHREAD_MUTEX_INITIALIZER; //定義和初始化互斥鎖
pthread_mutex_t w_mutex = PTHREAD_MUTEX_INITIALIZER;
int readers = 0; //記錄讀者的個數
寫模式:
pthread_mutex_lock(&w_mutex);
寫寫寫……
pthread_mutex_unlock(&w_mutex);
讀模式:
pthread_mutex_lock(&r_mutex);
if(readers == 0)
pthread_mutex_lock(&w_mutex);
readers++;
pthread_mutex_unlock(&r_mutex);
讀讀讀……
pthread_mutex_lock(&r_mutex);
readers- -;
if(reader == 0)
pthread_mutex_unlock(&w_mutex);
pthread_mutex_unlock(&r_mutex);
用信號量來實現讀寫鎖
這裏使用2個信號量+1個整型變量來實現。令信號量的初始數值爲1,那麼信號量的作用就和互斥量等價了。
#include <semaphore.h> //線程信號量所需頭文件
sem_t r_sem; //定義信號量
sem_init(&r_sem, 0, 1); //初始化信號量
sem_t w_sem; //定義信號量
sem_init(&w_sem, 0, 1); //初始化信號量
int readers = 0;
寫模式:
sem_wait(&w_sem);
寫寫寫……
sem_post(&w_sem);
讀模式:
sem_wait(&r_sem);
if(readers == 0)
sem_wait(&w_sem);
readers++;
sem_post(&r_sem);
讀讀讀……
sem_wait(&r_sem);
readers- -;
if(readers == 0)
sem_post(&w_sem);
sem_post(&r_sem);