天天看點

讀寫鎖算法

背景:

在多線程程式設計中經常面臨這樣一個問題,同一個資料可以被多個線程同時讀取,但是同一時間隻能有一個線程對共享變量進行寫操作。

對該問題常用的解決方法時聲明一個鎖(互斥量)來對共享變量進行保護,這樣每次隻能有一個線程來對資料進行讀寫,會導緻讀取的效率低下。

讀寫鎖:

讀寫鎖算法主要實作對共享資源通路時,可以在多個線程間同時進行讀操作,但是在同一時間内隻能有一個線程對共享資源進行修改,并且在寫操作時不能有線程進行讀操作。

算法思想:

當進行讀操作時不能進行寫操作,是以當有讀操作時需要一把鎖來鎖住寫操作,由于允許多個線程同時讀操作,是以還需要一個變量(count)來記錄目前讀操作的線程個數,由于對count的修改需要互斥,是以還需要一個鎖用來儲存count的修改。

讀寫鎖的資料結構:

typedef struct RWLOCK_st

{

LOCK m_lReadLock;

LOCK m_lWriteLock;

int     m_icount;

} RWLOCK;

讀寫鎖操作僞代碼:

1. 聲明一個全局的鎖  RWLOCK  rwLock;

rwLock.m_icount = 0;

//讀操作時加鎖

RWLock_LockRead()

{

rwLock.m_lReadLock->lock()

rwLock.m_icount++;

if (rwLock.m_icount  == 1)

{

rwLock.m_lWriteLock->lock(); //鎖住寫操作,當有讀操作時隻鎖一次

}

rwLock.m_lReadLock->unlock()

}

RWLock_ReleaseRead()

{

rwLock.m_lReadLock->lock()

rwLock.m_icount--;

if (rwLock.m_icount  == 0)

{

rwLock.m_lWriteLock->unlock(); //允許寫操作

}

rwLock.m_lReadLock->unlock()

}

RWLock_LockWrite()

{

rwLock.m_lWriteLock->lock() //鎖住寫操作

}

RWLock_ReleaseWrite()

{

rwLock.m_lWriteLock->unlock() 

}

從 RWLock_LockWrite() 和RWLock_ReleaseWrite()中可以看出當進行寫操作時如果有讀操作會阻塞在RWLock_ReleaseRead()函數rwLock.m_lWriteLock->lock()處,當一個線程完成寫操作後,讀操作會和寫操作線程競争rwLock.m_lWriteLock->lock()。

讀寫鎖缺點:

優點上面已經說過。

1. 進行讀操作時會進行再次加鎖和解鎖操作,計算開銷比較大,是以對鎖内計算比較小的操作不适合使用讀寫鎖。

2. 如果讀操作比較密集,使得rwLock.m_icount永遠不可能為0,是以會使寫操作線程餓死。

參考:《多核計算與程式設計》,周偉明

繼續閱讀