windows與linux線程同步對比

1.1        Windows線程同步

1.1.1   關鍵代碼區Critical Section

所謂“關鍵代碼區”,相信大家看名字也能理解個大概了。首先:它很關鍵,第二:它是代碼區。之所以關鍵,當然目的就是每次只能一個線程能夠進入;既然是代碼區,那就是只能在一組擁有同樣代碼的線程中用。

那什麼情況下會用到關鍵代碼區呢?當然是要保護多個線程都會用到的東西了,說到這裏,想必你已經猜到了:全局變量和靜態變量。

1.1.2   互斥Mutex

互斥看起來和關鍵代碼區是一樣的,都是每次都是隻允許一個線程使用。但互斥和關鍵代碼區相比,具有如下特點:

對比點

關鍵代碼區

互斥

備註

名字

無名字

有名字

NA

跨進程

不能跨進程

可以跨進程

因爲有名字,所以可以跨進程

訪問模式

沒有超時

可以超時

NA

死鎖問題

線程掛了其它線程就只能傻等了

線程掛了,操作系統會通知其它線程

NA

運行環境

用戶區

內核區

所以關鍵代碼區性能要高一些。

 

1.1.3   信號量Semaphore

信號量本質上就是一個計數器,當計數器大於0時就意味着被保護的對象可用。每次申請計數器就減1,釋放就加1.

信號量和互斥體相比,一個最明顯的差別就在於互斥體每次只能有一個線程進行訪問,而信號量可以有多個線程進行訪問。

看到這裏,大家可能都像我開始一樣存在這樣的問題:如果將信號量最大值設置爲1,那麼不就是相當於互斥量了嗎?

看起來是一樣的,而且在有些系統上也確實是這樣的,據說是互斥體底層就是信號量來實現的,或者乾脆就沒有互斥體(例如傳統UNIX),但在有的系統上還是有差別的,差別在於:申請和釋放是否要同一個線程完成,Windows就是這種形式。互斥體要求同一線程來申請和釋放,而信號量就可以由不同的線程申請和釋放(但是我很難想象這樣做有什麼好處,難倒要給一個線程集中獲取信號量,再來通知另外的線程工作?)。

1.1.4   事件Event

事件本質上是一個系統信號,即:發生了某件事情後,發一個信號給其它關心這件事情的線程。

從事件的本質上來看,事件不是爲了資源保護的,而是爲了線程間通知用的。舉個簡單的例子:Socket接收完一個消息後,將其放入隊列,然後需要通知消息處理線程進行處理。

大家想想,如果沒有事件通知會怎麼樣呢?那接收線程只能設一個定時器或者循環,定時甚至循環去查詢隊列中是否有消息,這種定時和循環處理是對系統性能的極大浪費,所以,有了事件後,就不用這麼浪費了。

 

1.2        Linux線程同步

介紹完Windows,Linux介紹就很方便了,就像上一篇博文提到的一樣,Windows和Linux其實很多地方相似,線程同步也不例外。

1.2.1   關鍵代碼區???

不好意思,Linux沒有這個東東。

1.2.2   互斥Mutex

Linux和Windows是一樣的,這裏就不詳細介紹了,需要注意的是傳統UNIX並沒有互斥這個東東,傳統UNIX的互斥是通過二元信號量(即最大值爲1)來實現的。

1.2.3   信號量Semaphore

需要注意的是Linux中信號量有兩種:一種是內核POSIX標準的信號量,一種是用戶態的傳統UNIX IPC信號量。兩者的差別如下:

對比點

POSIX Semaphore

IPC Semaphore

備註

控制者

內核

用戶

IPC Semaphore可以通過semctrl函數修改對外表現。

權限控制

不允許修改

用戶可修改

NA

性能

優於IPC

劣於POSIX

NA

範圍

進程級

系統級

如果進程退出時忘記關閉,POSIX會自動釋放。

POSIX信號量和Windows的信號量是一樣的。

1.2.4   條件變量Conditions

看到這個名字有點莫名其妙,條件變量和線程同步有什麼關係呢?

但其實是Linux(或者是POSIX)的名字取得不好才導致我們很難理解,本質上條件變量就是Windows的事件,作用也是一樣的。唉,如果Linux或者POSIX不想和Windows同名,改成叫“通知”也能讓我們這些小蝦多省點腦力啊:)

發佈了57 篇原創文章 · 獲贊 108 · 訪問量 39萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章