[英]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
對象),它會延遲到第一個線程退出該塊,因此兩個線程不能同時更改塊內變量的值。
在這里,您的“共享資源”是您在塊中更改的變量:如我所見, objects
和obj.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.