自旋锁与读写锁
自旋鎖:
自旋鎖類似于互斥鎖,它的性能比互斥鎖更高。
自旋鎖與互斥鎖很重要的一個區別在于:線程在申請自旋鎖的時候,線程不會被掛起,它處于等待的狀態。
從 實現原理上來講,Mutex屬于sleep-waiting類型的鎖。例如在一個雙核的機器上有兩個線程(線程A和線程B),它們分別運行在Core0和 Core1上。假設線程A想要通過pthread_mutex_lock操作去得到一個臨界區的鎖,而此時這個鎖正被線程B所持有,那么線程A就會被阻塞 (blocking),Core0 會在此時進行上下文切換(Context Switch)將線程A置于等待隊列中,此時Core0就可以運行其他的任務(例如另一個線程C)而不必進行忙等待。而Spin lock則不然,它屬于busy-waiting類型的鎖,如果線程A是使用pthread_spin_lock操作去請求鎖,那么線程A就會一直在 Core0上進行忙等待并不停的進行鎖請求,直到得到這個鎖為止。
所以,自旋鎖一般用用多核的服務器。
自旋鎖與互斥鎖有點類似,只是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那里看是 否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是因此而得名。其作用是為了解決某項資源的互斥使用。因為自旋鎖不會引起調用者睡眠,所以自旋鎖的效率遠 高于互斥鎖。雖然它的效率比互斥鎖高,但是它也有些不足之處:
1、自旋鎖一直占用CPU,他在未獲得鎖的情況下,一直運行--自旋,所以占用著CPU,如果不能在很短的時 間內獲得鎖,這無疑會使CPU效率降低。
2、在用自旋鎖時有可能造成死鎖,當遞歸調用時有可能造成死鎖,調用有些其他函數也可能造成死鎖,如 copy_to_user()、copy_from_user()、kmalloc()等。
因此我們要慎重使用自旋鎖,自旋鎖只有在內核可搶占式或SMP的情況下才真正需要,在單CPU且不可搶占式的內核下,自旋鎖的操作為空操作。自旋鎖適用于鎖使用者保持鎖時間比較短的情況下。
讀寫鎖: 讀寫鎖用于讀稱為共享鎖,讀寫鎖用于寫稱為排他鎖;
只要沒有線程持有給定的讀寫鎖用于寫,那么任意數目的線程可以持有讀寫鎖用于讀;
僅當沒有線程持有某個給定的讀寫鎖用于讀或者寫的時候,才能分配讀寫鎖用于寫;
讀寫鎖有三種狀態:讀加鎖狀態、寫加鎖狀態和不加鎖狀態
一次只有一個線程可以占有寫模式的讀寫鎖,但是多個線程可以同時占有讀模式的讀寫鎖。(這也是它能夠實現高并發的一種手段)
當讀寫鎖在寫加鎖模式下,任何試圖對這個鎖進行加鎖的線程都會被阻塞,直到寫進程對其解鎖。
當讀寫鎖在讀加鎖模式下,任何線程都可以對其進行讀加鎖操作,但是所有試圖進行寫加鎖操作的線程都會被阻塞,直到所有的讀線程都解鎖。
所以讀寫鎖非常適合對數據結構讀的次數遠遠大于寫的情況。
如果嚴格按照上述讀寫鎖的操作進行的話,那么當讀者源源不斷到來的時候,寫者總是得不到讀寫鎖,就會造成不公平的狀態。
一種避免這種不公平狀態的方法是:
當處于讀模式的讀寫鎖接收到一個試圖對其進行寫模式加鎖操作時,便會阻塞后面對其進行讀模式加鎖操作的線程。
這樣等到已經加讀模式的鎖解鎖后,寫進程能夠訪問此鎖保護的資源。
總結
- 上一篇: 【LISP】为什么Lisp语言如此先进?
- 下一篇: 一个方法多个return_用这个方法可以