1. 程式人生 > >12、第七周-網絡編程 - 線程中的信號量(Semaphore)

12、第七周-網絡編程 - 線程中的信號量(Semaphore)

eas pytho 下一步 臨界資源 第七周 人才 超時 自己 運行

  

  互斥鎖同時只允許一個線程更改數據,而Semaphore是同時允許一定數量的線程更改數據。簡單介紹如下:

  信號量用在多線程多任務同步的,一個線程完成了某一個動作就通過信號量告訴別的線程,別的線程再進行某些動作。而互斥鎖是用在多線程多任務互斥的,一個線程占用了某一個資源,那麽別的線程就無法訪問,直到這個線程unlock,其他的線程才開始可以利用這 個資源。比如對全局變量的訪問,有時要加鎖,操作完了,在解鎖。有的時候鎖和信號量會同時使用的。
  也就是說,信號量不一定是鎖定某一個資源,而是流程上的概念,比如:有A,B兩個線程,B線程要等A線程完成某一任務以後再進行自己下面的步驟,這個任務 並不一定是鎖定某一資源,還可以是進行一些計算或者數據處理之類。而線程互斥鎖則是“鎖住某一資源”的概念,在鎖定期間內,其他線程無法對被保護的數據進 行操作。在有些情況下兩者可以互換。

信號量(Semaphore),有時被稱為信號燈,是在多線程環境下使用的一種設施, 它負責協調各個線程, 以保證它們能夠正確、合理的使用公共資源。

  • 創建 Create
  • 等待 Wait::線程等待信號量,如果值大於0,則獲得,值減一;如果只等於0,則一直線程進入睡眠狀態,知道信號量值大於0或者超時。
  • 釋放 Post:執行釋放信號量,則值加一;如果此時有正在等待的線程,則喚醒該線程。
  • 試圖等待 TryWait:如果調用TryWait,線程並不真正的去獲得信號量,還是檢查信號量是否能夠被獲得,如果信號量值大於0,則TryWait返回成功;否則返回失敗。
  • 銷毀 Destroy

  Mutex本質上說就是一把鎖,提供對資源的獨占訪問,所以Mutex主要的作用是用於互斥。Mutex對象的值,只有0和1兩個值。這兩個值也分別代表了Mutex的兩種狀態。值為0, 表示鎖定狀態,當前對象被鎖定,用戶進程/線程如果試圖Lock臨界資源,則進入排隊等待;值為1,表示空閑狀態,當前對象為空閑,用戶進程/線程可以Lock臨界資源,之後Mutex值減1變為0。

Mutex可以被抽象為四個操作:

  • 創建 Create
  • 加鎖 Lock
  • 解鎖 Unlock
  • 銷毀 Destroy

互斥鎖和信號量的區別:

  • 互斥量用於線程的互斥,信號量用於線程的同步。這是互斥量和信號量的根本區別,也就是互斥和同步之間的區別。
  1. 互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。
  2. 信號:是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源
  • 互斥量值只能為0/1,信號量值可以為非負整數。
  1. 也就是說,一個互斥量只能用於一個資源的互斥訪問,它不能實現多個資源的多線程互斥問題。信號量可以實現多個同類資源的多線程互斥和同步。當信號量為單值信號量是,也可以完成一個資源的互斥訪問。
  • 互斥量的加鎖和解鎖必須由同一線程分別對應使用,信號量可以由一個線程釋放,另一個線程得到

舉例:有三個公共電話亭,同時可以三個人打電話。這時候有人過來要打電話,就出現了等待。要等會裏面的人出來後(裏面的人出來這一動作,就相當於信號,告訴外面的人,到你打電話了),外面的人才能進去,進行下一步操作。

import threading,time

def run(n):
    semaphore.acquire()
    time.sleep(1)
    print ("run the  thread:%s\n " % n)
    semaphore.release()

if __name__ == "__main__":
    semaphore = threading.BoundedSemaphore(4) #最多允許4個線程同時運行
    for i in range(10):
        t = threading.Thread(target=run,args=(i,))
        t.start()
while threading.active_count() != 1:
    pass
else:
    print("--all thread done--")
輸出:
run the  thread:0
run the  thread:1
run the  thread:2
run the  thread:3
 
run the  thread:4
run the  thread:7
run the  thread:5
run the  thread:6
 
run the  thread:9
run the  thread:8
 
--all thread done--
Process finished with exit code 0

備註:每次執行4個線程,等前面執行完成後,在進行下一個。最後剩下兩個,會一起執行。整個執行過程中是無序的。

12、第七周-網絡編程 - 線程中的信號量(Semaphore)