在python aiohttp socketio中是否可能有竞争条件?
我正在编写类似于下面代码的代码。有时程序停止工作,或者我在访问socketio会话时遇到奇怪的错误。慢慢地,我觉得这可能是比赛条件 它更多的是伪代码。我想演示一下,我从多个协同路由访问全局共享状态和socketio会话在python aiohttp socketio中是否可能有竞争条件?,python,asynchronous,race-condition,aiohttp,python-socketio,Python,Asynchronous,Race Condition,Aiohttp,Python Socketio,我正在编写类似于下面代码的代码。有时程序停止工作,或者我在访问socketio会话时遇到奇怪的错误。慢慢地,我觉得这可能是比赛条件 它更多的是伪代码。我想演示一下,我从多个协同路由访问全局共享状态和socketio会话 这里肯定有个问题: for sid in app["sockets"]: # you are iterating over a list here await sio.save_session(...) # your coroutine will yield here
这里肯定有个问题:
for sid in app["sockets"]: # you are iterating over a list here
await sio.save_session(...) # your coroutine will yield here
您正在迭代列表app[“sockets”]
,并且在每次迭代中使用wait
关键字。当使用wait
关键字时,将支持您的协同程序,事件循环将检查是否可以执行或恢复另一个协同程序
假设connect(…)
coroutine在session\u路由
等待时运行
app["sockets"].append(sid) # this changed the structure of the list
connect(…)
更改了列表的结构。此可以使该列表当前存在的所有迭代器无效。disconnect(…)
coroutine也是如此
因此,要么不要修改列表,要么至少不要在列表更改后重用迭代器。后一种解决方案在这里更容易实现:
for sid in list(app["sockets"]):
await sio.save_session(...)
现在for循环在原始列表的副本上迭代。现在更改列表不会“干扰”副本
但是请注意,副本无法识别列表中的添加和删除
因此,简而言之,您的问题的答案是是,但它与异步io无关。同步代码中很容易出现同样的问题:
for i in my_list:
my_list.remove(1) # don't do this
另一个选项是使用
asyncio.Lock
保护套接字列表,以便套接字上的循环和套接字的添加和删除不能相互交织。所有添加和删除操作都将等待保存循环完成后进行。如果在列表中获得锁并移除该锁,那么您在最后指出的问题将导致死锁。
for i in my_list:
my_list.remove(1) # don't do this