Python並行編程(五):線程同步之信號量


1、基本概念

      信號量是由操作系統管理的一種抽象數據類型,用於在多線程中同步對共享資源的使用。本質上說,信號量是一個內部數據,用於標明當前的共享資源可以有多少並發讀取。

      同樣在threading中,信號量有acquire和release兩個函數。

      - 每當線程想要讀取關聯了信號量的共享資源時,必須調用acquire,此操作減少信號量的內部變量,如果此變量的值非負,那么分配該資源的權限。如果是負值,那么線程被掛起,直到有其他的線程釋放資源。

      - 當線程不再需要該共享資源,必須通過release釋放,這樣,信號線的內部變量增加,在信號量等待隊列中排在最前面的線程會拿到共享資源的權限。

      

      信號量同步機制在線程操作為原子操作時,才會沒有問題,但如果不是原子操作,或者兩個操作有一個終止了,就會出現問題,比如:

      有兩個並發線程,都在等待一個信號量,假設目前信號量的內部值為1,再假設線程A將信號量的值從1減到0,此時線程A拿到資源權限,這時候如果控制器切換到了線程B,線程B將信號量的值從0減到-1,並且在這里被掛起等待,這時控制器回到線程A,信號量已經成為了負值,於是第一個線程也在等待。盡管當時的信號量是可以讓線程訪問資源的,但是因為非原子操作導致了所有的線程都在狀態。

 

2、信號量的使用

      使用信號量進行線程同步例子:

# coding: utf-8
import threading
import time
import random

semaphore = threading.Semaphore(0)

def consumer():
    print("Consumer is waiting.")
    semaphore.acquire()
    print("Consumer notify: Consumed item number %s" %item)

def producer():
    global item
    time.sleep(10)
    item = random.randint(0, 100)
    print("Producer notify: Produced item number %s" %item)
    semaphore.release()

if __name__ == "__main__":
    for i in range(0, 5):
        t1 = threading.Thread(target=producer)
        t2 = threading.Thread(target=consumer)
        t1.start()
        t2.start()
        t1.join()
        t2.join()
    print("Program terminated")

      信號量被初始化為0,semaphore = threading.Semaphore(0),目的是同步兩個或多個線程。線程必須並行運行,所以需要信號量同步。

      如果信號量的計數器到了0,就會阻塞acquire方法,直到得到另一個線程的通知。如果信號量的計數器大於0,就會對這個值-1然后分配資源。

 

3、補充

      信號量的一個特殊用法是互斥量。互斥量是初始值為1的信號量,可以實現數據、資源的互斥訪問。

      信號量在支持多線程的編程語言中應用很廣,但是他也有可能造成死鎖的情況。例如,有一個線程t1,先等待信號量s1,然后等待信號量s2,而線程t2會先等待信號量s2,然后再等待信號量s1,這樣就會發生死鎖,導致t1等待s2,但是t2在等待s1。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM