Python 当使用多线程时,我应该保护内置数据结构(列表、dict)吗?

Python 当使用多线程时,我应该保护内置数据结构(列表、dict)吗?,python,Python,我认为我应该在使用多个线程时使用Lock对象来保护自定义类,然而,因为Python使用GIL来确保在任何给定时间只有一个线程在运行,这是否意味着不需要使用Lock来保护内置类型(如list)?例如 num_list = [] def consumer(): while True: if len(num_list) > 0: num = num_list.pop() print num retu

我认为我应该在使用多个线程时使用Lock对象来保护自定义类,然而,因为Python使用GIL来确保在任何给定时间只有一个线程在运行,这是否意味着不需要使用Lock来保护内置类型(如list)?例如

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()

@杰里米·布朗用文字解释(见下文)。。。但如果你想要一个反例:

锁不能保护你的状态。以下示例不使用锁,因此,如果
xrange
值足够高,将导致失败:
索引器:从空列表弹出。

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()

@杰里米·布朗用文字解释(见下文)。。。但如果你想要一个反例:

锁不能保护你的状态。以下示例不使用锁,因此,如果
xrange
值足够高,将导致失败:
索引器:从空列表弹出。

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()

GIL保护的是解释器状态,而不是你的状态。有些操作实际上是原子操作——它们需要一个字节码,因此实际上不需要锁定。(请参阅一位非常著名的Python贡献者的回答)

不过,在这方面并没有任何好的文档,所以我一般不会依赖它,除非您计划分解字节码来测试您的假设。如果您计划从多个上下文修改状态(或修改和访问复杂状态),那么您应该计划使用某种锁定/同步机制


如果你有兴趣从不同的角度来处理这类问题,你应该研究一下模块。Python代码中的一种常见模式是使用同步队列在线程上下文之间通信,而不是使用共享状态。

GIL保护解释器状态,而不是您的状态。有些操作实际上是原子操作——它们需要一个字节码,因此实际上不需要锁定。(请参阅一位非常著名的Python贡献者的回答)

不过,在这方面并没有任何好的文档,所以我一般不会依赖它,除非您计划分解字节码来测试您的假设。如果您计划从多个上下文修改状态(或修改和访问复杂状态),那么您应该计划使用某种锁定/同步机制


如果你有兴趣从不同的角度来处理这类问题,你应该研究一下模块。Python代码中的一种常见模式是使用同步队列在线程上下文之间通信,而不是使用共享状态。

为什么不生成一个工作示例。。。。。它不止运行一次……为什么不提供一个有效的示例。。。。。这不止一次。。。。