当前位置: 首页 > 知识库问答 >
问题:

当调用condition_all()时,多个线程(正在等待条件变量)如何获取相关锁?

柴英光
2023-03-14

从理论上讲,一个等待线程(假设Thread_1)首先获取一个互斥体,然后通过调用wait()等待条件变量。对wait()的调用会立即解锁互斥体。当另一个线程(比如Thread_2)调用notify()时,等待的线程(Thread_1)被唤醒,相同的互斥体在等待之前被锁定(..)调用返回。

现在假设多个线程在给定的时间等待一个条件变量(假设是Thread_1、Thread_2和Thread_3)。现在另一个线程(Thread_4)调用notify_all(),它将通知所有3个正在等待条件变量的线程。当它们被唤醒时,它们3个如何锁定互斥体,这应该发生在等待之前(...)通话回报?只有一个线程(3个等待线程中的一个)可以获取互斥体。那么notify_all()的目的是什么,如果它只能解锁一个线程的话?notify()和notify_all()的结果有什么不同(从等待线程的角度来看)?

共有1个答案

冷俊健
2023-03-14

他们三个怎么都能锁互斥锁?

他们一次锁一个,就像往常一样。

wait(...) 函数可以像这样实现:

def wait(cond_var, mutex):
    tricky_internal_wait(cond_var, mutex)
    lock(mutex)

tricky_internal_wait(c, m)函数将自动解锁互斥锁并阻止与cond_var关联的队列上的调用线程,但没有理由为什么它末尾的lock(互斥锁)调用需要与普通的lock(互斥锁)有任何不同。

当在上面的示例中通知cond_var时,线程将唤醒,然后调用lock(mutex),然后如果其他线程已经锁定了互斥体,则操作系统将阻塞与互斥体相关联的队列上的调用方。调用方无法从wait()调用返回,直到它从lock()调用返回;在互斥体可用且调用方获得互斥体之前,调用方无法返回lock()。就像<code>lock()

< code>wait(c,m)的实际实现可能会更有效:它可能会将线程直接从< code>cond_var队列移动到< code>mutex队列,而不会在< code>mutex已经被其他线程使用时唤醒线程。

那么notify_all()的目的是什么,如果它只能解锁一个线程呢?

它不会只解锁一个。它解除了所有的障碍,。。。

...一次一个。

假设一些线程T调用notify_all(cond_var),而线程X、Y和Z都在等待fobar()中的条件:

def foobar():
    lock(mutex)
    while condition_is_not_satisfied():
        wait(cond_var, mutex)
    do_some_thing_that_requires_condition_to_be_satisfied()
    unlock(mutex)

也许线程Z将是第一个从etc()调用中返回的。它会再次检查以查看条件是否真的满足,然后它会做事情,然后它会解锁互斥锁并从fobar()返回。

在线程Z解锁互斥体并返回之前,线程X和Y将无法从< code>wait()调用中返回。

也许在Z解锁互斥锁后,下一个从等待()返回的将是X。然后X将检查是否满足条件。也许Z的动作意味着条件不再满足。在这种情况下,X将再次wait()wait()调用将释放互斥锁。或者,也许条件仍然满足,X会做这件事,显式解锁互斥锁并从fobar()返回。

无论哪种方式,线程X都会释放互斥锁,然后线程Y将能够从etc()调用返回...

...事情就这样过去了。

 类似资料:
  • 我正在研究哲学家进餐问题,n位哲学家轮流思考和进餐。我想有一个版本,哲学家们会按照id的顺序进食:0,1,2,3,4。。。,但是我的线程一直被阻塞。我的线程从调用PhilosopherThread开始。 我想把哲学家们整理好有点麻烦。我只能在线程堵塞之前吃前2个线程。 编辑:据我所知,我这样做是对的。我首先锁定互斥锁,然后检查pindex是否是当前线程id,如果不是,线程将等待,直到pindex等

  • 问题内容: 我找不到如何测量线程等待锁定的时间。我必须确定一个线程是否正在等待锁定超过1秒,如果需要,则运行另一个线程。谢谢! 问题答案: 试试这个:

  • 我有一个接受客户端连接的服务器程序。这些客户端连接可以属于多个流。例如,两个或多个客户机可以属于同一个流。在这些流中,我必须传递一条消息,但我必须等到所有流都建立起来。为此,我维护以下数据结构。 整数是流 ID,长整型是客户端编号。为了使给定流的一个线程等待原子龙达到特定值,我使用了以下循环。实际上,流的第一个数据包会将其放入流 ID 和要等待的连接数。对于每个连接,我都会减少要等待的连接。 然而

  • 问题内容: 有什么方法可以简单地等待所有线程处理完成?例如,假设我有: 如何更改此方法,以便该方法在注释处暂停直到所有线程的方法退出?谢谢! 问题答案: 你将所有线程放入数组中,全部启动,然后进行循环 每个连接将阻塞,直到相应的线程完成为止。线程的完成顺序可能不同于你加入线程的顺序,但这不是问题:退出循环时,所有线程均已完成。

  • 正在使用和原始人的线程吗? 许多月前,我学会了如何在Android上编写多线程Java代码。我记得我必须创建线程、启动线程等等。 现在我正在学习Javascript,我刚刚学习了和。 例如: 这看起来比我以前做的简单多了,而且更直观。 将首先启动,然后启动快速函数(),然后将等待,直到两个函数在日志记录之前解决-和和可能同时运行。我希望这最终取决于浏览器是否是独立的线程。但看起来它走路和说话就像粗

  • 我正在查看一个jstack日志,下面是我看到的: “com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2”#250 daemon prio=5 os_prio=0 tid=0x00007F9DE0016000 nid=0x7e54 runnable[0x00007F9D6495A000]java.lang.Thread.St