繁体   English   中英

python 多线程:如何确保线程正在等待而不是当前加入?

[英]python multithreading: how to ensure a thread is waiting and not currently joining?

我有一个永久监听事件的线程 A。 当特定资源 R1 的事件到达时,它启动线程 B 并将作业传递给 B 进行处理。 然后线程 A 继续监听,而 B 等待作业,从线程 A 接收作业并处理它。 资源 R1 的附加事件也被发送到线程 B(放置在线程 B 的队列中)。 资源 R2、R3 等的事件被类似地处理,为每个唯一资源启动一个新线程,即。 线程 C 用于 R2,线程 D 用于 R3,依此类推。 对于特定资源,事件的性质是高峰期,随后是长时间没有任何事件,因此线程 A 启动线程 B,当 B 完成作业时,它等待来自 A 的另一个作业,如果没有作业到达,它就加入。 因为线程 B 在完成前一个事件的作业后可能仍在等待,所以线程 A 在将 B 传递给当前作业之前检查 B 是否处于活动状态(将其放入队列中)。 如果它还活着,A 只是将作业传递给 B,如果不是,它会启动线程 B,然后再次将作业传递给它。 为了确保特定资源的事件序列化,每个资源只启动一个线程(否则这将是微不足道的,只需为每个事件启动一个新线程)

现在,问题来了:有一小段时间,线程 B 刚刚在等待作业时超时,将要加入,但还没有加入。 如果线程 A 在那么短的时间内检查线程 B 是否存活,线程 A 将看到 B 存活并向其发送作业,但 B 不会处理它,因为它不再等待作业 - 相反它正在加入. 因此,作业未被处理。 这可以通过在线程 B 的最后一行代码中插入一个睡眠语句来模拟。

我如何确保当线程 A 检查线程 B 是否处于活动状态并且正在等待作业并且当前没有加入? 我考虑过使用锁,但获取锁也需要时间,即使时间非常短。

使用锁和标志

线程 A 和线程 B 之间共享的 state 如下所示:

lock = Lock()
queue = list()
live = False

在线程A中,当一个事件进来时:

with lock:
    if not live:
        spawn_thread_b()
        live = True
    queue.append(event)

在线程 B 中,循环如下所示:

while True:
    events = list()

    with lock:
        if not queue:
            break # No events, so let the thread exit the loop
        
        events, queue = queue, list() # Swap 'queue' with a new empty list

    for event in events:
        process(event)

with lock:
    live = False

通过此实现,可以在生成新线程 B 时让线程 B 加入。 但在我看来,这是不可避免的,实际上不是问题,因为这两个线程不会干扰(多亏了锁)。

保持线程存活

另一种解决方案是简单地让线程 B 保持活动状态。 当没有事件进来时,它只会等待。 查看条件变量以实现等待新事件。

如果您拥有大量资源并且希望事件稀疏地分布在这些资源上,那么我理解您不想让线程无限期地保持活动状态的愿望。

如果您只有有限数量的资源,那么保持线程活动可能是解决问题的更直接的方法。 连续的线程生命周期管理很麻烦,在某些场景下甚至会影响性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM