我认为在使用多个线程时我应该使用Lock对象来保护自定义类,但是,因为Python使用GIL来确保在任何给定时间只运行一个线程,这是否意味着不需要使用Lock来保护内置类型列表?例如,
num_list = []
def consumer():
while True:
if len(num_list) > 0:
num = num_list.pop()
print num
return
def producer():
num_list.append(1)
consumer_thread = threading.Thread(target = consumer)
producer_thread = threading.Thread(target = producer)
consumer_thread.start()
producer_thread.start()
答案 0 :(得分:1)
GIL保护翻译状态,而不是你的状态。有些操作实际上是原子的 - 它们需要单个字节码,因此实际上不需要锁定。 (请参阅is python variable assignment atomic?以获得来自声誉卓着的Python撰稿人的答案)。
关于这一点并没有任何好的文档,所以我不会依赖它,除非你打算反汇编字节码来测试你的假设。如果您计划从多个上下文修改状态(或修改和访问复杂状态),那么您应该计划使用某种锁定/同步机制。
如果您对从不同角度处理此类问题感兴趣,请查看Queue模块。 Python代码中的一个常见模式是使用同步队列在线程上下文之间进行通信,而不是使用共享状态。
答案 1 :(得分:0)
锁不能保护你的状态。以下示例不使用锁定,因此如果xrange
值足够高,则会导致失败:IndexError: pop from empty list.
import threading
import time
con1_list =[]
con2_list =[]
stop = 10000
total = 500000
num_list = []
def consumer(name, doneFlag):
while True:
if len(num_list) > 0:
if name == 'nix':
con2_list.append(num_list.pop())
if len(con2_list) == stop:
print 'done b'
return
else:
con1_list.append(num_list.pop())
if len(con1_list) == stop:
print 'done a'
return
def producer():
for x in xrange(total):
num_list.append(x)
def test():
while not (len(con2_list) >=stop and len(con1_list) >=stop):
time.sleep(1)
print set(con1_list).intersection( set(con2_list))
consumer_thread = threading.Thread(target = consumer, args=('nick',done1))
consumer_thread2 = threading.Thread(target = consumer, args=('nix',done2))
producer_thread = threading.Thread(target = producer)
watcher = threading.Thread(target = test)
consumer_thread.start();consumer_thread2.start();producer_thread.start();watcher.start()