我对Python中的多线程有相当基本的理解,对asyncio
也有更基本的er理解。
我目前正在编写一个基于诅咒的小程序(最终将使用完整的GUI,但这是另一个故事),该程序处理主线程中的UI和用户IO,然后有两个其他守护进程线程(每个线程都有自己的队列/工作方法-从队列中获取信息):
watcher
线程,它监视将要发生的基于时间和条件的事件(如发送到消息板、接收到的消息等),然后将所需的任务放入。。。worker
)守护进程线程的队列,然后完成它们。这三个线程都在同时运行,这就引出了一些问题:
worker
线程的队列(或者更一般地说,任何线程的队列)为空时,应该停止它,直到它有事情要做,还是可以继续运行?当并发线程除了监视其队列之外不做任何事情时,它们是否会占用大量的处理能力?watcher
线程持续运行一个方法,我猜worker
线程将能够从watcher
线程放入的单个队列中提取任务。watcher
线程应该像那样连续运行吗?根据我的理解,如果我错了,请纠正我,asyncio
应该用于基于事件的多线程处理,这似乎与我要做的事情有关。谢谢!
您应该只使用阻塞调用
queue.get()
。这将使线程在I/O上阻塞,这意味着GIL将被释放,并且不会使用任何处理能力(或者至少是非常少量的处理能力)。不要在while
循环中使用非阻塞gets,因为这需要更多的CPU唤醒。如果观察者所做的一切只是从队列中取出一些东西,然后立即将其放入另一个队列中,在该队列中它会被一个工作线程消耗掉,那么听起来这是不必要的开销—您也可以直接在工作线程中消耗它。不过,我不太清楚情况是否如此,观察者是在排队消费,还是只是把物品放进一个队列?如果它是从队列中消费的,谁会把东西放进去?
是的,这是受吉尔的影响。一次只能有一个线程运行Python字节码,因此无法获得真正的并行性,除非线程运行I/O(这会释放GIL)。如果您的工作线程正在执行CPU绑定的活动,您应该认真考虑通过
multiprocessing
在单独的进程中运行它,如果可能的话。很难说,因为我不知道“连续跑步”到底是什么意思。它一直在做什么?如果它把大部分时间都花在睡眠或阻塞上,那就没问题了——这两样东西都会释放GIL。如果它一直在做实际的工作,那就需要GIL,从而降低应用程序中其他线程的性能(假设它们试图同时做工作)。
asyncio
是为I/O绑定的程序设计的,因此可以在单个线程中运行,使用异步I/O。根据您的worker
所做的操作,您的程序可能非常适合这种情况。任何一个主要等待I/O的程序都有可能适合于
asyncio
-但前提是你能找到一个能让诅咒(或者你最终选择的任何其他GUI库)很好地使用它的库。大多数GUI框架都有自己的事件循环,这将与asyncio
的事件循环冲突。您需要使用一个库,该库可以使GUI的事件循环与asyncio
的事件循环很好地配合。您还需要确保可以找到应用程序使用的任何其他基于同步I/O的库的asyncio
兼容版本(例如数据库驱动程序)。也就是说,从基于线程的程序切换到基于
asyncio
的程序,您不太可能看到任何性能改进。它可能也会有同样的表现。因为您只处理3个线程,所以在它们之间切换上下文的开销不是很大,所以从这一点切换到单线程异步I/O方法不会有很大的区别。asyncio
将有助于避免线程同步的复杂性(如果这是你的应用程序的一个问题-目前还不清楚),并且至少在理论上,如果你的应用程序可能需要大量的线程,那么它的伸缩性会更好,但事实似乎并非如此。我认为对于您来说,基本上取决于您喜欢使用哪种样式(假设您可以找到所需的所有asyncio
兼容库)。相关问题 更多 >
编程相关推荐