首页 文章

字典在多线程应用程序的迭代期间改变了大小

提问于
浏览
1

我不知道如何解决这个问题:

回溯(最近一次调用最后一次):文件“/usr/local/cabinet_dev/cabinet/lib/python3.4/site-packages/eventlet/hubs/hub.py”,第458行,在fire_timers中定时器()文件“/ usr / local / cabinet_dev / cabinet / lib / python3.4 / site-packages / eventlet / hubs / timer.py“,第58行,在调用cb(* args,** kw)文件”/ usr / local / cabinet_dev / cabinet / lib / python3.4 / site-packages / eventlet / greenthread.py“,第218行,主结果=函数(* args,** kwargs)文件”./monitor.py“,第148行,在caughtBridge中call in self.active.keys():RuntimeError:字典在迭代期间改变了大小

在下面的代码中:

def caughtBridge(self):
    while True:
        event = self.bridgeQueue.get()
        uniqueid1 = str(event.headers.get('Uniqueid1'))
        uniqueid2 = str(event.headers.get('Uniqueid2'))
        for call in self.active.keys():
            if self.active[call]['uniqueid'] == uniqueid1:
                self.active[call]['uniqueid2'] = uniqueid2
            if self.active[call]['uniqueid'] == uniqueid1:
                for listener in self.listeners:
                    for number in listener.getNumbers():
                        if number == self.active[call]['exten']:
                            if not self.active[call]['answered']:
                                self.sendEvent({"status": "bridge", "id": self.active[call]['uniqueid'],
                                                "number": self.active[call]['exten']},
                                               listener.getRoom())
                                self.__callInfo(self.active[call], listener.getRoom())
                                self.active[call]['answered'] = True
        self.bridgeQueue.task_done()

1 回答

  • 2

    使用 self.active.keys() 的副本,例如:

    for call in list(self.active.keys()):
    

    没看到你是 addremove dict 参赛作品?
    如果是 adding ,其他线程将看不到添加的 dict 条目 .
    removing 的情况下,当前线程将失败 Key Error
    你必须 grab 这些 .

    例如:

    for call in list(self.active.keys()):
        <Lock that call to prevent removing>
        if call in self.active:
            ...
                          self.active[call]['answered'] = True
        else:
            # call removed do nothing
        <Unlocked that call to do whatever in other Thread>
    self.bridgeQueue.task_done()
    

    阅读Python»3.6.2文档:threading.html#lock-objects

    基本上实现Pair方法 self.lock(call)self.unlock(call) ,例如:

    未经测试的代码:为了防止死锁,你必须保证self.unlock(呼叫)将被达到! class xxx
    def __init __....
    self_lock = threading.Lock
    #Init all self.active [call] ['lock'] = False

    def lock(self,call):
    #self._lock ist class threading.Lock
    所有线程的#self._lock必须相同
    与self._lock:
    如果调用self.active而不是self.active [call] ['lock']:
    self.active [call] ['lock'] =真
    返回True
    其他:
    返回False

    解锁(自我,通话):
    与self._lock:
    self.active [call] ['lock'] = False

    #用法:
    对于列表中的调用(self.active.keys()):
    如果self.lock(调用):
    ...
    self.active [call] ['answers'] =真

    self.unlock(通话)
    其他:
    #call删除什么都不做
    self.bridgeQueue.task_done()

相关问题