簡體   English   中英

python threading.Lock() 是否鎖定所有需要鎖定的東西?

[英]Does python threading.Lock() lock everything that needs locking?

下面的腳本是抽象的。 我的問題是關於threading.Lock()的使用

鎖定限制了對“共享資源”的訪問,但我對這能走多遠感到緊張。 我的對象屬性是對象列表,在此示例中,這些對象的屬性是數組 在某些情況下,依賴性會走得更遠。

Lock()是否確實“知道”需要鎖定的所有內容?

還顯示了以下腳本的輸出。 該腳本的目的主要是為了討論——它不會失敗,但我不確定它是否鎖定了它需要的一切。

start:   [array([0, 1]), array([0, 1, 2]), array([0, 1, 2, 3])]
append an object
done!
finish:  [array([505, 605]), array([10, 11, 12]), array([10, 11, 12, 13]), array([5])]


import time
from threading import Thread, Lock
import numpy as np

class Bucket(object):
    def __init__(self, objects):
        self.objects = objects

class Object(object):
    def __init__(self, array):
        self.array = array

class A(Thread):
    def __init__(self, bucket):
        Thread.__init__(self)
        self.bucket      = bucket
    def run(self):
        nloop            = 0
        locker           = Lock()
        n = 0
        while n < 10:
            with locker:  
                objects = self.bucket.objects[:]  # makes a local copy of list each time
            for i, obj in enumerate(objects):
                with locker:
                    obj.array += 1
                time.sleep(0.2)
            n += 1
            print 'n: ', n
        print "done!"
        return

objects = []
for i in range(3):
    ob = Object(np.arange(i+2))
    objects.append(ob)
bucket = Bucket(objects)

locker           = Lock()

a = A(bucket)
print [o.array for o in bucket.objects]

a.start()

time.sleep(3)

with locker:
    bucket.objects.append(Object(np.arange(1)))  # abuse the bucket!
    print 'append an object'
time.sleep(5)

print [o.array for o in bucket.objects]

你似乎誤解了鎖的工作原理。

鎖不鎖定任何對象,它只能鎖定線程執行

嘗試進入with locker:塊的第一個線程成功。

如果另一個線程試圖進入一個with locker:塊(具有相同的locker對象),它會延遲到第一個線程退出該塊,因此兩個線程不能同時更改塊內變量的值。

在這里,您的“共享資源”是您在塊中更改的變量:如我所見, objectsobj.array 您基本上是在保護它們免受並發訪問(即 - 在沒有 GIL 的 python 版本中)只是因為一次只有一個線程可以更改它們

老前輩稱之為臨界區,一次只能執行 1 個線程。

請注意,對不同的資源使用相同的locker對象有點可疑。 這有更多的機會死鎖/比它需要的更慢。

(如果你with locker調用嵌套 2,你會遇到死鎖——如果你想這樣做,你需要一個 RLock)

就這么簡單。

鎖對您要嘗試做的事情一無所知 它只是一把鎖,它不在乎你把它放在哪里。

例如,您可以聲明:

lock = threading.Lock()

接着:

with lock:
    # Do stuff.

# In another thread
with lock:
    # Do something else

除非當前塊完成,否則所有其他帶有with lock的塊都無法執行,它與塊中的內容無關。 所以對於這個例子,假設第一個#Do stuff正在運行,當第二個線程遇到with lock: # Do something else時,它不會運行,因為有相同的鎖。 如果您正在進行面向對象的編程,使用self.lock是個好主意。

更好的說,multiprocessing Lock 不是一把鎖,而是一把鑰匙。 如果我們有幾個代碼塊的一把鑰匙,我們只能用它一次打開其中一個(鎖或鑰匙獲取)。 當密鑰忙時,其他要求相同密鑰的代碼塊將無法執行並等待。 所以它只會阻塞一些代碼,阻止解釋器執行它。

暫無
暫無

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

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