簡體   English   中英

threading.Lock()性能問題

[英]threading.Lock() performance issues

我有多個線程:

dispQ = Queue.Queue()
stop_thr_event = threading.Event()

def worker (stop_event):
    while not stop_event.wait(0):
        try:
            job = dispQ.get(timeout=1)
            job.waitcount -= 1
            dispQ.task_done()
        except Queue.Empty, msg:
            continue

# create job objects and put into dispQ here
for j in range(NUM_OF_JOBS):
    j = Job()
    dispQ.put(j)

# NUM_OF_THREADS could be 10-20 ish
running_threads = []
for t in range(NUM_OF_THREADS):
    t1 = threading.Thread( target=worker, args=(stop_thr_event,) )
    t1.daemon = True
    t1.start()
    running_threads.append(t1)


stop_thr_event.set()
for t in running_threads:
    t.join()

上面的代碼給了我一些非常奇怪的行為。 我最終發現這是由於等待計數遞減而沒有鎖定

我已經在Job類中添加了一個屬性self.thr_lock = threading.Lock()然后將其更改為

with job.thr_lock:
    job.waitcount -= 1

這似乎可以解決奇怪的問題,但性能似乎有所下降。

這是預期的嗎? 有沒有辦法優化鎖定?
每個作業對象擁有一個全局鎖而不是一個鎖會更好嗎?

關於“優化”線程的唯一方法是將處理分解為可以同時執行的工作塊或工作塊。 這主要意味着執行輸入或輸出(I / O),因為這是解釋器唯一的釋放全局解釋器鎖定(也就是GIL)的時間。

實際上,除非滿足上述條件,否則由於使用線程的開銷,添加線程時通常沒有收益,甚至沒有凈增長。

如果對所有共享資源使用單個全局鎖,那可能會更糟,因為它會使程序的某些部分在真正不需要時等待,因為它不會區分需要什么資源,因此不必要的等待會發生。

您可能會發現David Beasley在PyCon 2015演講中題為“ 底層開始進行Python並發” 它涵蓋了線程,事件循環和協程。

根據您的代碼很難回答您的問題。 鎖確實有一些固有的成本,沒有免費的東西,但是通常它很小。 如果您的工作量很小,則可能需要考慮“分塊”它們,這樣相對於每個線程完成的工作量,獲取/釋放調用要少得多。

一個相關但獨立的問題是線程彼此阻塞。 如果許多線程正在等待相同的鎖,則可能會注意到較大的性能問題。 在這里,您的線程處於空閑狀態,彼此等待。 在某些情況下,這是無法避免的,因為存在共享資源,這是性能瓶頸。 在其他情況下,您可以重新組織代碼以避免這種性能損失。

您的示例代碼中有些東西使我覺得它可能與實際應用程序有很大不同。 首先,示例代碼不會在線程之間共享作業對象。 如果您不共享作業對象,則不需要鎖定它們。 其次,按照編寫的示例代碼,可能無法在完成之前清空隊列。 一旦您單擊stop_thr_event.set() ,它將退出,並將任何剩余的作業stop_thr_event.set()隊列,這是設計stop_thr_event.set()嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM