UNIX網絡編程-鎖(二)

此博客是關於一篇信號量的文章,信號量提供進程間互斥,很方便。用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-讀鎖

相關文章
相關標籤/搜索