linux中mutex和semaphore的區別

2021-06-19 16:26:35 字數 3037 閱讀 3188

很多程式設計的書裡在介紹mutex和semaphore的時候都會說,mutex是一種特殊的semaphore.

當semaphore的n=1時,就變成了binary semaphore,也就等同與mutex了。

但是實際上,在linux中,他們的實現什有區別的,導致最後應用的行為也是有區別的。

先看下面這個例子,這是一段linux kernel的**:

[cpp]view plain

copy

#include 

#include 

#include 

#include 

#include 

#include 

static

define_mutex(g_mutex);  

static

define_semaphore(g_semaphore);  

static

intfun1(

void

*p)  

return

0;  

}  static

intfun2(

void

*p)  

return

0;  

}  static

intfun3(

void

*p)  

return

0;  

}  static

intfun4(

void

*p)  

return

0;  

}  static

inthello_init(

void

)    

module_init(hello_init);  

這段**很簡單,4個執行緒,2個去獲取mutex,2個去獲取semaphore。

我們可以先只enable thread1和thread2。

我開始預期的結果什輸出1212121212...

但是實際的結果是111111111...22222222222...11111111111...

假設enable thread3和thread4,輸出則變成了34343434343434...

顯然,mutex和semaphore使用的結果不一樣。

為什麼會造成這樣的結果哪?

我們分析一下kernel裡mutex和semaphore的實現就可以明白了

kernel/mutex.c

[cpp]view plain

copy

__mutex_unlock_common_slowpath(atomic_t *lock_count, 

intnested)  

spin_unlock_mutex(&lock->wait_lock, flags);  

}  

在解鎖的時候,會先把lock->count設定成1,

然後從等待這個mutex的佇列裡取出第乙個任務,並wake_up這個任務。

這裡要注意,wake_up_process只是把這個任務設定成可排程,並不是直接就進行排程了。

所以當乙個執行緒unlock mutex之後,只要在自己還沒有被排程出去之前再次很快的lock mutex的話,他依舊會成功。

於是,這就出現了一開始那個程式的結果。

在**本身沒有死鎖的情況下,不合適得使用mutex,會造成飢餓的發生。

那semaphore到底是如何避免這樣的情況發生的哪?

kernel/semaphore.c

[cpp]view plain

copy

void

down(

struct

semaphore *sem)  

static

inline

int__sched __down_common(

struct

semaphore *sem, 

long

state,  

long

timeout)  

timed_out:  

list_del(&waiter.list);  

return

-etime;  

interrupted:  

list_del(&waiter.list);  

return

-eintr;  

}  void

up(struct

semaphore *sem)  

static

noinline

void

__sched __up(

struct

semaphore *sem)    

首先在down的時候,回去檢視sem->count的值,假如大於0,就進行--操作。

這就好比第乙個執行緒去down semaphore。

等到第二個執行緒再去down的時候,count為0了,就進入了__down_common函式。

這個函式裡面會一直檢查waiter.up,知道為true了才會退出。

至此,第二個執行緒就被block在了down函式裡。

等到第乙個執行緒up semaphore,假如這個semaphore的等待佇列裡還有任務,則設定waiter->up為true並喚醒任務。

這裡用的也是wake_up_process,貌似和mutex的實現什一樣的,但是接下來就不一樣了。

假設第乙個執行緒之後又很快的去down semaphore,會發生什麼哪?

由於sem->count還是為0,這個執行緒在down的時候就會被block住而發生排程。

第二個執行緒此時就可以獲得semaphore而繼續執行**了。

一直直到沒有任何執行緒在等待佇列裡了,sem->count才會被++。

所以,semaphore就變成了這樣的行為。

總結:mutex在使用時沒有任何順序的保證,它僅僅是保護了資源,但是效率會比較高。

而semaphore則有順序的保證,使得每個使用者都能依次獲得他,但是相應的會損失一點效率。

linux中mutex和semaphore的區別

很多程式設計的書裡在介紹mutex和semaphore的時候都會說,mutex是一種特殊的semaphore.當semaphore的n 1時,就變成了binary semaphore,也就等同與mutex了。但是實際上,在linux中,他們的實現什有區別的,導致最後應用的行為也是有區別的。先看下面這...

SEM和SEM如何互相幫助?

sem和seo是 搜尋營銷的標配,如果把這兩種方式打個比方的話,sem相當於醫生給開的處方藥 止痛藥 seo相當於醫生給開的處方藥 抗生素 抗生素 seo 是醫生專門用來給患者從根本上解決病痛的處方藥,缺點在於,你不知道什麼時候會治好,以及以後會不會又犯病 seo在執行的時候,很難立馬見效,時間很長...

sd和sem啥區別 SD與SEM區別

sd 標準差 standard deviation 中文環境中又常稱均方差,但不同於均方誤差 mean squared error,均方誤差是各資料偏離真實值的距離平方的平均數,也即誤差平方和的平均數,計算公式形式上接近方差,它的開方叫均方根誤差,均方根誤差才和標準差形式上接近 標準差是離均差平方和...