因为只有当你在改变列表的任何地方都使用锁时,锁才会起作用,所以如果你只在一个地方调用它,它就不是一个在任何地方都有效的咒语。
要保护列表,您需要在两个线程上添加锁定上下文:
lock = threading.Lock()
def createstuff(data):
t= threading.Thread(target=func, args=(data,))
t.start()
def func(val):
with lock:
print 'thread: acquired'
time.sleep(2)
print ('Value: %s, : %s'%(val, threading.currentThread().getName()))
print 'thread released'
ags_list = ['x']
createstuff(ags_list)
with lock:
print 'thread: acquired'
rn =random.randint(5,50)
print 'random no:', rn
ags_list[0] = rn
print 'thread: released'
您可以创建一个线程安全列表,例如:
class ThreadSafeList(list):
def __init__(self, *args):
super(ThreadSafeList, self).__init__(*args)
self.lock = threading.Lock()
def __setitem__(self, idx, value):
with self.lock:
print 'list acquired'
super(ThreadSafeList, self)[idx] = value
print 'list released'
然后使用它:
def createstuff(data):
t= threading.Thread(target=func, args=(data,))
t.start()
def func(val):
time.sleep(2)
print ('Value: %s, : %s'%(val, threading.currentThread().getName()))
args_list = ThreadSafeList(['x'])
createstuff(args_list)
rn =random.randint(5,50)
print 'random no:', rn
args_list[0] = rn
当然这只是一个例子,还有待完善和完善。在这里我更愿意集中讨论这一点。
尽管您不需要在线程中锁定,因为从列表中访问值是(事实上)原子只读操作,因此列表的突变只能发生在列表中访问值之前或之后,而不是发生因为它正在访问该值。所以最终你的例子中不应该有任何种族问题。
如果您正在修改列表的值,或者对数据进行非原子访问,那么锁可能会很有用。
注意:如果您认为它可以以任何其他方式工作:互斥机制(通过实现Lock
)不保护数据,它保护两个执行线程不同时执行。如果你断言锁定Thread A,在断言相同的锁之前Thread B, Thread B会等待Thread A解除锁定直到完成其工作。