Table of Contents
此博客是關於一篇信號量的文章,信號量提供進程間互斥,很方便。用mutex來實現信號量的功能,必須將mutex創建在共享內存上才能實現。因此當須要線程間互斥的時候,最好是用mutex;當用進程間互斥的時候,用sem。歸結起來,mutex直接用到進程上,顯得無用; sem用到線程上,顯得多此一舉。git
1.1 信號量API
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);github
建立一個信號量,value值很重要,初始化信號量的爲value。編程
int sem_unlink(const char *name);網絡
依據名字來銷燬信號量函數
sem_t *sem_open(const char *name, int oflag);post
打開一個已經存在的信號量spa
int sem_close(sem_t *sem);線程
關閉一個信號量,並非銷燬它,依舊存在於內核中,只是從當前進程中卸載。指針
int sem_wait(sem_t *sem);xml
sem的值爲0,就一直等待;不然就將sem的值-1
int sem_trywait(sem_t *sem);
sem的值爲0,就放棄等待,返回值EAGAIN;不然就將sem的值-1
int sem_post(sem_t *sem);
sem的值+1
int sem_getvalue(sem_t *sem, int *
若是返回成功,sval就是sem當前值;不然就獲取值出錯了
1.2 信號量互斥鎖的實現
信號量的互斥鎖的類爲SemMutex。
1.2.1 成員變量以下:
Sem mutex_; Sem實際上封裝了一個sem*指針,初始化爲SEM_FAILED
std::string name_; 信號量的名稱
1.2.2 實現的成員函數以下:
SemMutex(const char* name);
構造函數初始化Mutex的名稱
bool Create();
調用sem_open, 建立信號量, 重要的是信號量的計數初始化爲1
bool Destroy();
銷燬信號量
bool Open();
打開已經建立的信號量
bool IsOpen();
信號量是否已經打開,實際上判斷sem指針是否爲SEM_FAILED
bool Lock();
調用sem_wait, 若是信號量的值當前爲0,一直等待,表示已經佔用了鎖資源; 不然sem的值就-1
bool UnLock();
調用sem_post, 釋放鎖資源,sem的值+1
bool TryLock();
調用sem_trywait, 若是鎖資源已經佔用,sem的值爲0,就不用等待,直接返回EAGAIN。
int LockStatus();
獲取鎖的狀態, -1 ,錯誤,0 - 加鎖狀態,1 - 無鎖狀態;實際上其調用sem_getvalue來獲取sem的計數,來查看狀態的。 實際上,實現互斥信號量,就是實現一個2值信號量,信號量的值一直在0和1之間變化;1 的時候是無鎖狀態,不會阻塞;0的時候是加鎖狀態,就會阻塞。
1.3 信號量讀寫鎖的實現
信號量讀寫鎖的實現,須要一個Sem來記錄同時正在read的個數,以及一個SemMutex來實現互斥,其類爲RWSem。
其關鍵就是鎖狀態的斷定了。
p_mutex_->LockStatus == UNLOCK; 代表無鎖
p_mutex_->LockStatus == LOCK && p_read_->GetValue() == 0; 已經加了寫鎖, 即已經加鎖,可是讀鎖的個數爲0
p_mutex_->LockStatus == LOCK && p_read_->GetValue() > 0; 已經加了讀鎖, 即已經加鎖,可是讀鎖的個數>0
1.3.1 RWSem的成員變量:
SemMutex* p_mutex_; 實現讀寫互斥
Sem* p_read_; 記錄當前正在讀鎖的個數
1.3.2 RWSem的成員函數:
bool Create();
建立p_mutex_和p_read_
bool Destroy();
銷燬p_mutex_和p_read_
bool Open();
打開p_mutex_和p_read_
bool Close();
關閉p_mutex_和p_read_
bool WLock();
嘗試讀鎖,當讀鎖已經佔住了資源或者寫鎖站住資源,就會失敗;而無論哪一種鎖佔用了資源,p_mutex_的LockStatus都是鎖住狀態。 實現機制就是調用p_mutex_的Wait就OK了
bool TryWLock();
嘗試讀鎖,當讀鎖已經佔住了資源或者寫鎖站住資源,就會失敗;而無論哪一種鎖佔用了資源,p_mutex_的LockStatus都是鎖住狀態。 實現機制就是調用p_mutex_的TryWait就OK了
bool TryRLock();
當寫鎖佔住資源的時候,返回false
當寫鎖沒佔住資源而且讀鎖也沒佔住資源的時候, p_read_調用Post,讀鎖的個數+1, 而且調用p_mutex_->Wait(),
當寫鎖沒佔住資源而且讀鎖已經佔住資源的時候, p_read_調用Post, 讀鎖的個數+1, 不用調用p_mutex_->Wait(),不然會阻塞掉的。
bool RLock();
當寫鎖佔住資源的時候,調用p_mutex_->Wait(), 讓其阻塞
當寫鎖沒佔住資源而且讀鎖也沒佔住資源的時候, p_read_調用Post,讀鎖的個數+1, 而且調用p_mutex_->Wait(), 表示這個鎖資源已經被佔用
當寫鎖沒佔住資源而且讀鎖已經佔住資源的時候, p_read_調用Post, 讀鎖的個數+1, 不用調用p_mutex_->Wait(),不然會阻塞掉的。
bool UnLock();
當加的鎖爲讀鎖的時候,調用p_read_.Post(), 讀鎖的個數-1,若是讀鎖的個數減到0,就調用p_mutex_->Post(), 解除鎖資源的佔用
當加的是寫鎖的時候, 調用p_mutex_.Post(),
int LockStatus();
0 - 無鎖;1- 寫鎖;2-讀鎖