如何理解互斥鎖和信號量,以及他們在系統編程中是如何配合使用的?


Do not use semaphores.


互斥鎖和信號量的理解,引用@xiaole shang 的說法:」互斥鎖通常就是信號量值為1的簡化版本「

另外這裡講一個我碰到過的比較有趣的例子,是之前在做pintos的時候遇到的一個問題,就是出現搶鎖的情況,請看代碼:

lock_init(number_lock); //初始化了一個鎖
thread_create("sort_num", 1, sort_num, NULL);
lock_acquire(number_lock);//請求鎖,試圖將主程序阻塞,直到子線程執行完畢

這裡簡單介紹一下thread_create,它通過傳入一個函數名可以創建一個線程並在這個線程中執行這個函數,但thread_create這個函數是非同步的,所以它被調用後會繼續執行下一行代碼。

為了實現創建子線程後阻塞主程序,並且等到子線程執行完sort_num函數後再繼續執行主程序後面的代碼,我一開始嘗試這樣做:

我就在sort_num 函數的開始部分和結尾處加上了請求鎖和釋放鎖:

void sort_num() {
lock_acquire(number_lock); // 請求鎖
list_sort(number_list, com, NULL);
lock_release(number_lock); // 釋放鎖
};

這樣,我的想法是,通過創建一個鎖,然後在子線程裡面獲取這個鎖,這樣主程序在創建這個線程後,由於下一行代碼是一個請求鎖的操作,那麼主程序會阻塞在這裡,直到子線程sort_num執行完畢後釋放鎖,主程序才會繼續往下執行。

---------------------------------------------------------------------------

但是,運行結果並不如願,由於這是一個非同步的過程,創建線程的速度太慢,就會導致出現了搶鎖的情況,這樣在子線程還沒創建完的時候,主程序已經執行了下一行代碼獲取了鎖,然後繼續往下執行,等到子線程創建完畢後,運行sort_num函數會一直卡在一開始的請求鎖的那裡。

----------------------------------------------------------------------------

所以,遇到這樣的情況,我們就不能用鎖來實現控制線程調度,而需要使用到信號量,怎麼做呢?代碼如下:

sema_init(number_sema, 0); // 初始化一個值為0的信號量
thread_create("sort_num", 1, sort_num, NULL);
sema_down(number_sema); // 請求信號量

然後再看一下sort_num函數的做法:

void sort_num() {
list_sort(number_list, com, NULL);
sema_up(number_sema); // 釋放信號量
};

這裡用了一個方法

1. 首先,創建了一個初始值為0的信號量,並且在創建子線程的代碼後面請求信號量,但是由於信號量初始值為0,那麼將不會出現類似搶鎖的機制,因此主程序會阻塞在這裡直到有信號量資源被釋放。

2. 其次,我們在子線程調用的函數sort_num的最後,釋放了一個信號量資源。

3. 最後,子線程執行完畢,同時,主程序執行sema_down成功得到信號量後,繼續往下執行其他代碼。

=============================================

這個應該不算信號量和鎖的配合使用,不過應該能加深一下理解。


以下入門介紹是我以前在讀其他文獻時偶然遇到了,很抱歉已經記不得原作者了但是感覺講的一針見血,因此複述原文分享:

1. 信號量(Semaphore)

信號量就是一個停車場。

當前值是停車場里還剩下多少個空車位。

最大值是停車場里最多能容納多少個車位。

當汽車進入停車場時,首先要在門口排隊(sem_wait),得到進入許可後才能進入。

排隊順序原則上先到先得。

每進一輛車,停車場就少了1個停車位,即信號量當前值-1。

當前值為0時,停車場停滿了,所有車不得進入統統在門口排隊等。

當一輛車離開後,釋放其所佔據的停車位(sem_post),信號量當前值+1

信號量值得到釋放後,如果門口有正在排隊的車,那麼就放進來,每放進來一個就重複前面的步驟。

2. 互斥鎖(Mutex)

Mutex就是廁所的隔間

門開著的時候誰都可以進

但是一次只能進一個人

進去後就從裡面鎖上門

廁所里有人的時候其他人就要排隊等,直到裡面的人出來


互斥鎖通常就是信號量值為1的簡化版本。配合使用談不上吧,要根據具體情況來使用。


可以了解下 posix 的mutex , condition variable模型。此種模型相比信號量更 原子,靈活。更不容易出錯


Mutexes and Semaphores Demystified


推薦閱讀:

Linux進程間如何傳遞文件描述符?
linux下隱藏自己的文件和進程是如何做到的?
如何理解Linux中的OOM(Out Of Memory Killer)機制?
關於Linux的兩個問題?
linux下沒有root許可權如何方便地安裝軟體?

TAG:Linux | 計算機科學 | 系統編程 |