簡體   English   中英

Python dict.get()鎖定

[英]Python dict.get() Lock

當我使用dictionary.get()函數時,它會鎖定整個詞典嗎? 我正在開發一個多進程和多線程程序。 字典用作狀態表以跟蹤數據。 我必須對字典施加大小限制,因此每當達到該限制時,我都必須根據時間戳在表上進行垃圾回收。 當前的實現將在垃圾回收遍歷整個表時延遲添加操作。

我將有2個或更多線程,一個僅用於添加數據,另一個僅用於垃圾回收。 在我的程序中,性能對於處理流數據至關重要 我的程序正在接收流數據,並且每當收到一條消息時,它都必須在狀態表中查找它,然后首先添加不存在的記錄,或者復制某些信息,然后沿着管道發送。

我曾考慮過使用multiprocessing來同時執行搜索和添加操作,但是如果使用進程,則必須為每個進程制作狀態表的副本,在這種情況下,同步的性能開銷太高了。 而且我還讀到multiprocessing.manager.dict()也鎖定了每個CRUD操作的訪問權限。 我無法為此節省開銷,因此我目前的方法是使用線程。

所以我的問題是,當一個線程在執行.get() ,對表進行del dict['key']操作時,是否會阻止另一個插入線程訪問它?

注意:我已經閱讀了大多數SO的python詞典相關的文章,但似乎找不到答案。 即使python字典操作是原子的,大多數人也只會回答,使用Lock進行插入/更新會更安全。 我正在處理大量的流數據,因此每次鎖定對於我來說都不理想。 請告知是否有更好的方法。

如果對字典中的鍵進行散列或比較的過程可以調用任意Python代碼(基本上,如果鍵不是用C實現的所有Python內置類型,例如strintfloat等),則可以,在解決桶沖突(在相等性測試期間)時釋放GIL的情況下,有可能發生競爭狀態,而另一個線程可能會跳入並導致被比較的對象從dict消失。 他們試圖確保它實際上不會使解釋程序崩潰,但是過去一直是錯誤的來源。

如果有這種可能(或者您使用的是非CPython解釋器,沒有GIL提供這種基本保證),那么您應該真正使用鎖來協調訪問。 在CPython上,只要您使用的是現代Python 3,成本就會相當低。 鎖上的爭用應該相當低,因為GIL確保一次僅實際運行一個線程。 大多數情況下,您的鎖應該是無競爭的(因為爭用在GIL上),因此使用它的增量成本應該很小。

注意:您可以考慮使用collections.OrderedDict來簡化限制表大小的過程。 使用OrderedDict ,您可以通過向表中添加以下內容來將大小限制實現為嚴格的LRU(最近使用)系統:

with lock:
    try:
        try:
            odict.move_to_end(key) # If key already existed, make sure it's "renewed"
        finally:
            odict[key] = value  # set new value whether or not key already existed
    except KeyError:
        # move_to_end raising key error means newly added key, so we might
        # have grown larger than limit
        if len(odict) > maxsize:
            odict.popitem(False)  # Pops oldest item

用法如下:

with lock:
    # move_to_end optional; if using key means it should live longer, then do it
    # if only setting key should refresh it, omit move_to_end
    odict.move_to_end(key)
    return odict[key]

這確實需要一個鎖,但同時也減少了垃圾收集工作時,它的增長來自“檢查每一個鍵”(過大O(n)工作),以“流行的最古老的項目關閉不看別的”( O(1)工作)。

鎖用於避免爭用情況,因此,沒有兩個線程可以同時更改dict,因此使用鎖很明顯,否則可能會導致爭用,從而導致程序失敗。 互斥鎖可用於處理2個線程。

暫無
暫無

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

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