close

說來慚愧,程式寫了那麼久,坦白說還是前陣子接觸到某個專案時才知道原來還有SpinLock這個東西存在,用來提供鎖定的需求,趁還沒忘記的時候重新MEMO一下這四個東西的差異。

 

一、Critical Session (臨界區)

在還在唸書的時候,一直認為CS(後簡稱)是對於同時存取某個項目時為了避免互搶資源而先行鎖定這個概念的統稱,而Mutex與Semaphore則是不同的方法來達成這個概念。但直到工作後發現CS在Win32上是實際存在的一種方法,所以它既是一個鎖定的方法(在Windows上)也同時是一個概念。

Method: (限Win32)

CRITICAL_SESSION cs;
InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
LeaveCriticalSection(&cs);

在Win32上與Mutex方法最大的差別在於CS僅作用於同一個Process下的資料鎖定,而Mutex是跨Process的鎖定,需透過系統核心去協助處理,而CS因為僅對於自己Process處理,所以速度較快。非常適合用於Process內的MultiThread對於Global Memory的鎖定處理,而公用文件如檔案的IO則需透過Mutex。

 

二、Mutex (互斥鎖)

Method: (Win32 and Linux)

Win32
HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);

Linux
pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_destroy(pthread_mutex_t *mutex);

跨Process的鎖,系統層級,同時只能有一個人拿到鑰匙進入鎖定,是與Semaphore的主要分別。Mutex上鎖失敗時進程會進行Sleep,讓核心進行Content switch後去另一個進程進行解鎖後喚醒原本的進程,若鎖定時間很短的話在CPU的睡眠/喚醒成本上則顯得浪費,這時就是Spinlock表現的機會了。

 

三、Semaphore (信號量)

同時可以允許多個人取得鎖定直到定義的值,若該值設為1稱為Binary Semaphore,在大部分的系統下Binary Semaphore與Mutex幾乎沒有差異,網路上有一些文章在講Binary Semaphore與Mutex的差別比較深入,我就不贅述了,而且坦白說這個東西我沒實際使用過。

Method: 無

在C++並沒有實際針對Semaphore的type定義,通常就是自製Counter並使用Mutex進行類別封裝實作出來

參考連結

 

四、Spinlock (自旋鎖)

Spinlock算是現學現賣了,它是Busy-Waiting的概念跟一般Mutex是Sleep-Waiting不同,我的理解是一個Process在確認某個資源是否被鎖定時,若發現鎖住則透過while loop將自己卡住一瞬間後再去確認一次某個資源是否依然鎖定住,所以適合應用的情境是在短時間的鎖定。

事實上我自己應用鎖時大部分的操作通常都是短時間的鎖定,最常的就是鎖住某個map, vector然後變更裡面的內容後就釋放,因此都很適用Spinlock而且會有較佳的效能,但像對DB資料表的操作這種需要等待遠方回應或文件IO等有一段相當的時間的鎖定操作就不適合。

較佳的效能主因來自於由於是Busy-Waiting,因此不用付出像Mutex一樣Content switch成本,也因為這樣多核心是能使用Spinlock的基本條件,因為自身處於Busy-Waiting的狀態,若沒有另一個地方對鎖進行Unlock,等於會是永遠處於卡死的狀態。

Method: 無

C++一樣沒有預定義的Spinlock type,但網路上有很多寫好的open source可使用

參考連結

arrow
arrow

    不來嗯 發表在 痞客邦 留言(0) 人氣()