您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Python實現線程間同步的方法的內容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
線程間同步
如果多個線程共同對某個數據修改,則可能出現不可預料的結果,為了保證數據的正確性,需要對多個線程進行同步。
使用Thread對象的Lock和Rlock可以實現簡單的線程同步,這兩個對象都有acquire方法和release方法,對于那些需要每次只允許一個線程操作的數據,可以將其操作放到acquire和release方法之間。
需要注意的是,Python有一個GIL(Global Interpreter Lock)機制,任何線程在運行之前必須獲取這個全局鎖才能執行,每當執行完100條字節碼,全局鎖才會釋放,切換到其他線程執行。
線程同步問題
多線程實現同步有四種方式:
鎖機制,信號量,條件判斷和同步隊列。
下面我主要關注兩種同步機制:鎖機制和同步隊列。
(1)鎖機制
threading的Lock類,用該類的acquire函數進行加鎖,用realease函數進行解鎖
import threading import time class myThread(threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print("Starting " + self.name) # 獲得鎖,成功獲得鎖定后返回True # 可選的timeout參數不填時將一直阻塞直到獲得鎖定 # 否則超時后將返回False threadLock.acquire() print_time(self.name, self.counter, 5) # 釋放鎖 threadLock.release() def print_time(threadName, delay, counter): while counter: time.sleep(delay) print("%s: %s" % (threadName, time.ctime(time.time()))) counter -= 1 threadLock = threading.Lock() threads = [] # 創建新線程 thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # 開啟新線程 thread1.start() thread2.start() # 添加線程到線程列表 threads.append(thread1) threads.append(thread2) # 等待所有線程完成 for t in threads: t.join() print("Exiting Main Thread")
(2) 線程同步隊列queue
python2.x中提供的Queue, Python3.x中提供的是queue
見import queue.
Python的queue模塊中提供了同步的、線程安全的隊列類,包括FIFO(先入先出)隊列Queue,LIFO(后入先出)隊列LifoQueue,和優先級隊列PriorityQueue。這些隊列都實現了鎖原語,能夠在多線程中直接使用。可以使用隊列來實現線程間的同步。
queue模塊中的常用方法:
queue.qsize() 返回隊列的大小
queue.empty() 如果隊列為空,返回True,反之False
queue.full() 如果隊列滿了,返回True,反之False
queue.full 與 maxsize 大小對應
queue.get([block[, timeout]])獲取隊列,timeout等待時間
queue.get_nowait() 相當Queue.get(False)
queue.put(item) 寫入隊列,timeout等待時間
queue.put_nowait(item) 相當Queue.put(item, False)
queue.task_done() 在完成一項工作之后,Queue.task_done()函數向任務已經完成的隊列發送一個信號
queue.join() 實際上意味著等到隊列為空,再執行別的操作
案例1:
import queue import threading import time exitFlag = 0 class myThread(threading.Thread): def __init__(self, threadID, name, q): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.q = q def run(self): print("Starting " + self.name) process_data(self.name, self.q) print("Exiting " + self.name) def process_data(threadName, q): while not exitFlag: queueLock.acquire() if not workQueue.empty(): data = q.get() queueLock.release() print("%s processing %s" % (threadName, data)) else: queueLock.release() time.sleep(1) threadList = ["Thread-1", "Thread-2", "Thread-3"] nameList = ["One", "Two", "Three", "Four", "Five"] queueLock = threading.Lock() workQueue = queue.Queue(10) threads = [] threadID = 1 # 創建新線程 for tName in threadList: thread = myThread(threadID, tName, workQueue) thread.start() threads.append(thread) threadID += 1 # 填充隊列 queueLock.acquire() for word in nameList: workQueue.put(word) queueLock.release() # 等待隊列清空 while not workQueue.empty(): pass # 通知線程是時候退出 exitFlag = 1 # 等待所有線程完成 for t in threads: t.join() print("Exiting Main Thread")
案例2:
import time import threading import queue class Worker(threading.Thread): def __init__(self, name, queue): threading.Thread.__init__(self) self.queue = queue self.start() #執行run() def run(self): #循環,保證接著跑下一個任務 while True: # 隊列為空則退出線程 if self.queue.empty(): break # 獲取一個隊列數據 foo = self.queue.get() # 延時1S模擬你要做的事情 time.sleep(1) # 打印 print(self.getName() + " process " + str(foo)) # 任務完成 self.queue.task_done() # 隊列 queue = queue.Queue() # 加入100個任務隊列 for i in range(100): queue.put(i) # 開10個線程 for i in range(10): threadName = 'Thread' + str(i) Worker(threadName, queue) # 所有線程執行完畢后關閉 queue.join()
感謝各位的閱讀!關于Python實現線程間同步的方法就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。