5 python python-multithreading python-asyncio
我编写的代码似乎可以实现我想要的功能,但我不确定这是否是一个好主意,因为它混合了线程和事件循环以在主线程外运行无限循环。这是一个最小的代码片段,它体现了我正在做的事情的想法:
import asyncio
import threading
msg = ""
async def infinite_loop():
global msg
while True:
msg += "x"
await asyncio.sleep(0.3)
def worker():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.get_event_loop().run_until_complete(infinite_loop())
t = threading.Thread(target=worker, daemon=True)
t.start()
Run Code Online (Sandbox Code Playgroud)
主要思想是我有一个无限循环,每 0.3 秒操作一个全局变量。我希望这个无限循环在主线程之外运行,这样我仍然可以访问主线程中的共享变量。这在 jupyter 中特别有用,因为如果我run_until_complete在主线程中调用,我就无法再与 jupyter 交互。我希望主线程可用于交互式访问和修改msg. 在我的示例中,使用异步似乎没有必要,但我正在使用一个具有异步代码的库来运行服务器,因此这是必要的。我对 python 中的异步和线程很陌生,但我记得在某处读过/听到过,使用异步线程会带来麻烦......这是一个坏主意吗?我的方法是否存在潜在的并发问题?
我对 python 中的异步和线程很陌生,但我记得在某处读过/听到过,使用异步线程会带来麻烦......
对于初学者来说,混合异步和线程是不鼓励的,因为它会导致不必要的复杂化,并且通常源于对如何正确使用异步缺乏理解。刚接触 asyncio 的程序员通常会习惯性地使用线程,将它们用于协程更适合的任务。
但是,如果您有充分的理由生成一个运行 asyncio 事件循环的线程,请务必这样做 - 没有什么需要 asyncio 事件循环在主线程中运行。请注意仅从运行事件循环的线程(即从 asyncio 协程和回调)与事件循环本身进行交互(调用诸如call_soon、create_task、等方法)。stop要安全地与其他线程(例如您的情况下的主线程)的事件循环交互,请使用loop.call_soon_threadsafe()或asyncio.run_coroutine_threadsafe()。
请注意,设置全局变量等并不算作“交互”,因为 asyncio 不会观察这些变量。当然,由您负责处理线程间同步问题,例如使用锁保护对复杂可变结构的访问。
这是一个坏主意吗?
如果不确定是否混合线程和异步,您可以问自己两个问题:
run_in_executor等待阻塞代码的协程,我是否还需要线程?您的问题为这两个问题提供了很好的答案 - 您需要线程以便主线程可以与 jupyter 交互,并且您需要 asyncio 因为您依赖于使用它的库。
我的方法是否存在潜在的并发问题?
GIL 确保在一个线程中设置全局变量并在另一个线程中读取它不会出现数据争用,因此您所显示的内容应该没问题。
如果添加显式同步(例如多线程队列或条件变量),则应记住同步代码不得阻塞事件循环。换句话说,你不能只是threading.Event在 asyncio 协程中等待,比如 a,因为这会阻塞所有协程。相反,您可以等待一个,并使用来自其他线程的asyncio.Event类似内容来设置它。loop.call_soon_threadsafe(event.set)
| 归档时间: |
|
| 查看次数: |
4116 次 |
| 最近记录: |