有一種寫優(yōu)先讀寫鎖,有如下特點(diǎn):
1)多個(gè)讀者可以同時(shí)進(jìn)行讀
2)寫者必須互斥(只允許一個(gè)寫者寫,也不能讀者寫者同時(shí)進(jìn)行)
3)寫者優(yōu)先于讀者(一旦有寫者,則后續(xù)讀者必須等待,喚醒時(shí)優(yōu)先考慮寫者)
在Solaris 中直接提供了讀寫鎖, 但是在Linux 中只提供了線程的讀寫鎖, 這里記錄了一些讀寫鎖的資料.
1.Solaris .vs. Linux Posix 庫函數(shù)
Solaris 庫(lib 線程) | Linux POSIX 庫(libp 線程) | 操作 |
sema_destroy() | sem_destroy() | 銷毀信號(hào)狀態(tài)。 |
sema_init() | sem_init() | 初始化信號(hào)。 |
sema_post() | sem_post() | 增加信號(hào)。 |
sema_wait() | sem_wait() | 阻止信號(hào)計(jì)數(shù)。 |
sema_trywait() | sem_trywait() | 減少信號(hào)計(jì)數(shù)。 |
mutex_destroy() | pthread_mutex_destroy() | 銷毀或禁用與互斥對(duì)象相關(guān)的狀態(tài)。 |
mutex_init() | pthread_mutex_init() | 初始化互斥變量。 |
mutex_lock() | pthread_mutex_lock() | 鎖定互斥對(duì)象和塊,直到互斥對(duì)象被釋放。 |
mutex_unlock() | pthread_mutex_unlock() | 釋放互斥對(duì)象。 |
cond_broadcast() | pthread_cond_broadcast() | 解除對(duì)等待條件變量的所有線程的阻塞。 |
cond_destroy() | pthread_cond_destroy() | 銷毀與條件變量相關(guān)的任何狀態(tài)。 |
cond_init() | pthread_cond_init() | 初始化條件變量。 |
cond_signal() | pthread_cond_signal() | 解除等待條件變量的下一個(gè)線程的阻塞。 |
cond_wait() | pthread_cond_wait() | 阻止條件變量,并在最后釋放它。 |
rwlock_init() | pthread_rwlock_init() | 初始化讀/寫鎖。 |
rwlock_destroy() | pthread_rwlock_destroy() | 鎖定讀/寫鎖。 |
rw_rdlock() | pthread_rwlock_rdlock() | 讀取讀/寫鎖上的鎖。 |
rw_wrlock() | pthread_rwlock_wrlock() | 寫讀/寫鎖上的鎖。 |
rw_unlock() | pthread_rwlock_unlock() | 解除讀/寫鎖。 |
rw_tryrdlock() | pthread_rwlock_tryrdlock() | 讀取非阻塞讀/寫鎖上的鎖。 |
rw_trywrlock() | pthread_rwlock_trywrlock() | 寫非阻塞讀/寫鎖上的鎖。 |
2.使用mutex 來實(shí)現(xiàn)
設(shè)置三個(gè)互斥信號(hào)量:
rwmutex?? ??? ?用于寫者與其他讀者/寫者互斥的訪問共享數(shù)據(jù)
rmutex?? ??? ?用于讀者互斥的訪問讀者計(jì)數(shù)器readcount
nrmutex?? ??? ?用于寫者等待已進(jìn)入讀者退出,所有讀者退出前互斥寫操作
var?? rwmutex,rmutex,nrmutex:semaphore:=1,1,1; ?
int?? readcount=0;
cobegin
?? ?reader begin
?? ??? ?P(rwmutex);
?? ??? ?P(rmutex);
?? ??? ?readcount++;
?? ??? ?if (readcount == 1) P(nrmutex);? //有讀者進(jìn)入,互斥寫操作
?? ??? ?V(rmutex);
?? ??? ?V(rwmutex);? //及時(shí)釋放讀寫互斥信號(hào)量,允許其它讀、寫進(jìn)程申請(qǐng)資源讀數(shù)據(jù);
?? ??? ?
?? ??? ?P(rmutex);
?? ??? ?readcount--;
?? ??? ?if(readcount == 0) V(nrmutex);? //所有讀者退出,允許寫更新
?? ??? ?V(rmutex);
?? ?End
?? ?
?? ?writer begin
?? ??? ?P(rwmutex);??? //互斥后續(xù)其它讀者、寫者
?? ??? ?P(nrmutex);??? //如有讀者正在讀,等待所有讀者讀完
?? ??? ?寫更新;
?? ??? ?V(nrmutex);??? //允許后續(xù)新的第一個(gè)讀者進(jìn)入后互斥寫操作 ?
?? ??? ?V(rwmutex);??? //允許后續(xù)新讀者及其它寫者
?? ?End ?
coend??
3. 利用pthread_cond_* & pthread_mutex_* 實(shí)現(xiàn)rw_lock
#include?<pthread.h>
#include?<cstdlib>
#include?<ctime>
#include?<iostream>
using?namespace?std;
class?RWLock?{
private?:
????pthread_mutex_t?cnt_mutex;
????pthread_cond_t?rw_cond;
????int?rd_cnt,?wr_cnt;
????RWLock(const?RWLock&);
????RWLock&?operator=?(const?RWLock&);
public?:
????RWLock():?rd_cnt(0),wr_cnt(0)
????????{
????????????pthread_mutex_init(&cnt_mutex,?NULL);
????????????pthread_cond_init(&rw_cond,?NULL);
????????}
????void?get_shared_lock()
????????{
????????????pthread_mutex_lock(&cnt_mutex);
????????????while?(wr_cnt?>0)
????????????????{
????????????????????pthread_cond_wait(&rw_cond,&cnt_mutex);
????????????????}
????????????rd_cnt++;
????????????pthread_mutex_unlock(&cnt_mutex);
????????}
????void?release_shared_lock()
????????{
????????????pthread_mutex_lock(&cnt_mutex);
????????????rd_cnt--;
????????????if?(0?==?rd_cnt)
????????????????{
????????????????????pthread_cond_signal(&rw_cond);
????????????????}
????????????pthread_mutex_unlock(&cnt_mutex);
????????}
????void?get_exclusive_lock()
????????{
????????????pthread_mutex_lock(&cnt_mutex);
????????????while?(rd_cnt+wr_cnt>0)
????????????????{
????????????????????pthread_cond_wait(&rw_cond,&cnt_mutex);
????????????????}
????????????wr_cnt++;
????????????pthread_mutex_unlock(&cnt_mutex);
????????}
????void?release_exclusive_lock()
????????{
????????????pthread_mutex_lock(&cnt_mutex);
????????????wr_cnt--;
????????????pthread_cond_broadcast(&rw_cond);
????????????pthread_mutex_unlock(&cnt_mutex);
????????}
????~RWLock()
????????{
????????????pthread_mutex_destroy(&cnt_mutex);
????????????pthread_cond_destroy(&rw_cond);
????????}
};
class?Test
{
private?:????
????RWLock?lock;
????
????static?void*?shared_task_handler(void*?arg)
????????{
????????????Test*?testptr?=?static_cast<Test*>(arg);
????????????testptr->lock.get_shared_lock();
????????????//do?the?shared?task?here
????????????testptr->lock.release_shared_lock();
????????}
????static?void?*?exclusive_task_handler(void?*?arg)
????????{
????????????Test*?testptr?=?static_cast<Test*>(arg);
????????????testptr->lock.get_exclusive_lock();
????????????//do?the?exclusive?task?here
????????????testptr->lock.release_exclusive_lock();
????????}
public?:
????typedef?void*?(*ThreadFunc)?(void*);
????void?start()
????????{
????????????srand(time(NULL));
????????????const?int?THREADS_NO=rand()%100;
????????????pthread_t*?threads?=?new?pthread_t[THREADS_NO];
????????????for(int?i=0;?i<THREADS_NO;?i++)
????????????????{
????????????????????ThreadFunc?tmpfunc?=?rand()%2??shared_task_handler?:?exclusive_task_handler;
????????????????????if?(pthread_create(threads+i,NULL,tmpfunc,this))
????????????????????????{
????????????????????????????cerr?<<?"pthread_create?fails"?<<?endl;
????????????????????????????exit(1);
????????????????????????}
????????????????}
????????????for(int?i=0;?i<THREADS_NO;?i++)
????????????????{
????????????????????pthread_join(threads[i],NULL);
????????????????}
????????????delete[]?threads;
????????}
};
int?main()
{
????Test?tmptest;
????tmptest.start();
}
--------------------------
參考:
Solaris 執(zhí)行緒與同步機(jī)制之實(shí)例Posix線程編程指南