Python线程:在删除元素时进行迭代

时间:2018-03-03 21:07:59

标签: python multithreading thread-safety python-multithreading

我正在处理一个线程python程序。一个线程在列表上迭代(通过调用iterate)。另一个线程可能(很少)尝试使用remove_element从同一列表中删除元素:

my_list = [ large number of elements ]
def iterate():
   for item in my_list:
       yield item

def remove_element(x):
   my_list.remove(x)

我不想为迭代使用锁,因为迭代可能需要相当长的时间,而且我不想阻止编写器超过绝对必要的时间。

我担心如果作者在错误的时刻出现,我会在迭代线程中“丢失”元素:例如。如果迭代线程在元素1处,并且我删除元素0,则元素1变为新元素0并且迭代线程将“跳过”该元素。

问题1 :这是实际发生的事情,还是Python比那更聪明?

假设我是对的,我正在寻找解决方案。由于各种原因,我想要在迭代开始之前复制列表(它非常大,我需要尽可能多地保存内存)。所以我想到了以下解决方案:

当我在迭代时,我正在设置一个迭代正在进行的标志。如果删除线程注意到它,它不会立即删除该元素,而是将其添加到to_be_removed列表中以便以后删除。

在迭代线程中完成迭代后,它会检查to_be_removed中是否有元素并将其删除。

my_list = [ large number of elements ]
to_be_removed = []
iterating = False
lock = Threading.Lock()
def iterate():
   with lock:
      iterating = True
   try:
      for item in my_list:
          yield item
  finally:
      with lock:
         iterating = False
         while to_be_removed:
             my_list.remove(to_be_removed.pop())

def remove_element(x):
   with lock:
      if iterating:
          to_be_removed.append(x)
      else:
          my_list.remove(x)

问题2 :这是一个可靠的解决方案吗?是否有一个更简单的解决方案,不涉及创建要迭代的列表副本,并且在迭代期间不会阻止编写器?是否有可能提供我需要的标准库类?

0 个答案:

没有答案