首頁 >後端開發 >Python教學 >python中線程同步原語的程式碼範例

python中線程同步原語的程式碼範例

不言
不言轉載
2018-11-20 16:06:093073瀏覽

這篇文章帶給大家的內容是關於python中線程同步原語的程式碼範例,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

Threading模組是python3裡面的多執行緒模組,模組內整合了許多的類,其中包括Thread,Condition,Event,Lock,Rlock,Semaphore,Timer等等。以下這篇文章主要透過案例來說明其中的Event和Segmaphore(Boundedsegmaphore)的使用。

Event

Event類別內部保存著一個flags參數,標誌事件的等待與否。

Event類別實例函數

1. set() 將flags設定為True,事件停止阻塞

2. clear()  將flags重新設定為False,刪除flags ,事件重新阻塞

3. wait() 將事件設定為等待狀態

4.is_set()判斷flags是否被設定,如果被設定傳回True,否則回傳False

(1)單一事件等待其他事件的發生

 具體程式碼:

from time import ctime,sleep
event = Event()

def event_wait():
    print(ctime())
    event.wait()
    print('这是event_wait方法中的时间',ctime())

def event_set(n):
    sleep(n)
    event.set()
    print('这是event_set方法中的时间', ctime())

thread1 = Thread(target=event_wait)
thread2 = Thread(target=event_set,args=(3,))

thread1.start()
thread2.start()

結果:

Sat Nov 17 10:01:05 2018
这是event_wait方法中的时间 Sat Nov 17 10:01:08 2018
这是event_set方法中的时间  Sat Nov 17 10:01:08 2018

 (2)多個事件先後發生

下面以賽跑作為範例。假設5條跑道上,每條跑道各有一名運動員,分別為ABCDE。

具體程式碼:

from threading import Event
from  threading import Thread
import threading

event = Event()

def do_wait(athlete):
    racetrack = threading.current_thread().getName()
    print('%s准备就绪' % racetrack)
    event.wait()
    print('%s听到枪声,起跑!'%athlete)

thread1 = Thread(target=do_wait,args=("A",))
thread2 = Thread(target=do_wait,args=("B",))
thread3 = Thread(target=do_wait,args=("C",))
thread4 = Thread(target=do_wait,args=("D",))
thread5 = Thread(target=do_wait,args=("E",))

threads = []
threads.append(thread1)
threads.append(thread2)
threads.append(thread3)
threads.append(thread4)
threads.append(thread5)

for th in threads:
    th.start()

event.set()  #这个set()方法很关键,同时对5个线程中的event进行set操作

#結果:

Thread-1准备就绪
Thread-2准备就绪
Thread-3准备就绪
Thread-4准备就绪
Thread-5准备就绪
E听到枪声,起跑!
A听到枪声,起跑!
B听到枪声,起跑!
D听到枪声,起跑!
C听到枪声,起跑!

可以看出多個執行緒中event的set()是隨機的,其內部的實作是因為一個notify_all()方法。這個方法會一次釋放所有鎖住的事件,哪個執行緒先搶到執行緒執行的時間片,就先釋放鎖。

之所以能夠只呼叫一個set()函數就可以實作所有event的退出阻塞,是因為event.wait()是在執行緒內部實作的,而set()函式是在行程中調用, python多執行緒共享一個行程記憶體空間。如果是在不同進程中呼叫這兩個函數則無法實作。

BoundedSegmaphore

如果在主機執行IO密集型任務的時候再執行這種短時間內完成大量任務(多執行緒)的程式時,電腦就有很大可能會宕機。

這時候就可以為這段程式增加一個計數器(counter)功能,來限制一個時間點內的執行緒數量。當每次進行IO操作時,都需要向segmaphore請求資源(鎖),如果沒有請求到,就阻塞等待,請求成功才就像執行任務。

BoundedSegmaphore和Segmaphore的區別

BoundedSegmaphore請求的鎖數量固定為傳入參數,而Segmaphore請求的鎖數量可以超過傳入的參數。

主要函數:

1. acquire()  請求鎖定

2. release()   釋放鎖定

下面以一個租房的例子來說明這種固定鎖數量的機制。假設一家小公寓有6間房,原本有2個住戶在住。

特定程式碼實作:

from threading import BoundedSemaphore,Lock,Thread
from time import sleep
from random import randrange

lock = Lock()
num = 6
hotel = BoundedSemaphore(num)

def logout():
    lock.acquire()
    print('I want to logout')
    print('A customer logout...')
    try:
        hotel.release()
        print('Welcome again')
    except ValueError:
        print('Sorry,wait a moment.')
    lock.release()

def login():
    lock.acquire()
    print('I want to login')
    print('A customer login...')
    if hotel.acquire(False):
        print('Ok,your room number is...')
    else:
        print('Sorry,our hotel is full')
    lock.release()

#房东
def producer(loops):
    for i in range(loops):
        logout()
        print('还剩%s' % hotel._value, '房间')
        sleep(randrange(2))
#租客
def consumer(loops):
    for i in range(loops):
        login()
        print('还剩%s' % hotel._value, '房间')
        sleep(randrange(2))
def main():
    print('Start')
    room_num = hotel._value
    print('The hotel is full with %s room'%room_num)
    #原本有2个住户
    hotel.acquire()
    hotel.acquire()
    thread1 = Thread(target=producer,args=(randrange(2,8),))
    thread2 = Thread(target=consumer,args=(randrange(2,8),))
    thread1.start()
    thread2.start()

if __name__ == '__main__':
    main()

結果:

#
The hotel is full with 6 room
I want to logout
A customer logout...
Welcome again
还剩5 房间
I want to logout
A customer logout...
Welcome again
还剩6 房间
I want to login
A customer login...
Ok,your room number is...
还剩5 房间
I want to login
A customer login...
Ok,your room number is...
还剩4 房间

 可以看出,房間數目永遠不會超過6,因為_value值(BoundedSegmaphore內部的計數器counter)一定是傳入的參數6。

以上是python中線程同步原語的程式碼範例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除