2.5 核心中的併發
隨著多核膝上型電腦時代的到來,對稱多處理器(smp)的使用不再被限於高科技使用者。smp和核心搶占是多執行緒執行的兩種場景。多個執行緒能夠同時操作共享的核心資料結構,因此,對這些資料結構的訪問必須被序列化。
接下來,我們會討論併發訪問情況下保護共享核心資源的基本概念。我們以乙個簡單的例子開始,並逐步引入中斷、核心搶占和smp等複雜概念。
2.5.1 自旋鎖和互斥體
訪問共享資源的**區域稱作臨界區。自旋鎖(spinlock)和互斥體(mutex,mutual exclusion的縮寫)是保護核心臨界區的兩種基本機制。我們逐個分析。
自旋鎖可以確保在同時只有乙個執行緒進入臨界區。其他想進入臨界區的執行緒必須不停地原地打轉,直到第1個執行緒釋放自旋鎖。注意:這裡所說的執行緒不是核心執行緒,而是執行的執行緒。
下面的例子演示了自旋鎖的基本用法:
#include
spinlock_t mylock
= spin_lock_unlocked; /* initialize */
/*acquire the spinlock. this is inexpensive if there
* is no one inside the critical section. in the face of
* contention, spinlock() has to busy-wait.
*/spin_lock(
&mylock);
/* ... critical section code ... */
spin_unlock(
&mylock); /* release the lock */
與自旋鎖不同的是,互斥體在進入乙個被占用的臨界區之前不會原地打轉,而是使當前執行緒進入睡眠狀態。如果要等待的時間較長,互斥體比自旋鎖更合適,因為 自旋鎖會消耗cpu資源。在使用互斥體的場合,多於2次程序切換時間都可被認為是長時間,因此乙個互斥體會引起本執行緒睡眠,而當其被喚醒時,它需要被切換 回來。
因此,在很多情況下,決定使用自旋鎖還是互斥體相對來說很容易:
(1) 如果臨界區需要睡眠,只能使用互斥體,因為在獲得自旋鎖後進行排程、搶占以及在等待佇列上睡眠都是非法的;
(2) 由於互斥體會在面臨競爭的情況下將當前執行緒置於睡眠狀態,因此,在中斷處理函式中,只能使用自旋鎖。(第4章將介紹更多的關於中斷上下文的限制。)
下面的例子演示了互斥體使用的基本方法:
#include
/*statically declare a mutex. to dynamically
create a mutex, use mutex_init() */
static
define_mutex(mymutex);
/*acquire the mutex. this is inexpensive if there
* is no one inside the critical section. in the face of
* contention, mutex_lock() puts the calling thread to sleep.
*/mutex_lock(
&mymutex);
/* ... critical section code ... */
mutex_unlock(
&mymutex); /* release the mutex */
為了論證併發保護的用法,我們首先從乙個僅存在於程序上下文的臨界區開始,並以下面的順序逐步增加複雜性:
(1) 非搶占核心,單cpu情況下存在於程序上下文的臨界區;
(2) 非搶占核心,單cpu情況下存在於程序和中斷上下文的臨界區;
(3) 可搶占核心,單cpu情況下存在於程序和中斷上下文的臨界區;
(4) 可搶占核心,smp情況下存在於程序和中斷上下文的臨界區。
自旋鎖和互斥鎖
1.理論分析 從理論上說,如果乙個執行緒嘗試加鎖乙個互斥鎖的時候沒有成功,因為互斥鎖已經被鎖住了,這個未獲取鎖的執行緒會休眠以使得其它執行緒可以馬上執行。這個執行緒會一直休眠,直到持有鎖的執行緒釋放了互斥鎖,休眠的執行緒才會被喚醒。如果乙個執行緒嘗試獲得乙個自旋鎖的時候沒有成功,該執行緒會一直嘗試加...
自旋鎖和互斥鎖
自旋鎖是為實現保護共享資源而提出一種輕量級的鎖機制。自旋鎖屬於互斥鎖的一種,都是為了解決某項資源的互斥使用。理解 執行緒a正在占用cpu使用時,執行緒b也想要占用cpu,但此時a已經加了使用標誌 鎖 那麼b就可以有不同的操作 無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有乙個擁有者,也就說,在任何...
互斥鎖與自旋鎖
一 互斥鎖 當鎖時可用的,呼叫上鎖的api會成功,並且將鎖設定為不再可用。當乙個程序嘗試獲取不可用的鎖的時候它會阻塞,直到鎖被釋放。進入臨界區時獲得鎖,退出臨界區時釋放鎖。二 自旋鎖 是指當乙個執行緒在獲取鎖的時候,如果鎖已經被其它執行緒獲取,那麼該執行緒將迴圈等待,然後不斷的判斷鎖是否能夠被成功獲...