使线程等待条件,但允许线程在等待或侦听信号时保持可用

Make thread wait for condition but allow thread to remain usable while waiting or listening for a signal

鉴于线程 A 必须将工作分派给线程 B 的情况,是否有任何同步机制允许线程 A 不 return、但仍可用于其他任务,直到线程B完成,其中线程A可以return?

这不是特定于语言的,但是简单的 c 语言将是响应此问题的一个很好的选择。

这可能完全违反直觉;听起来确实如此,但在假设之前我必须先问...

请注意我感兴趣的 This is a made up hypothetical situation。我不是在寻找现有问题的解决方案,所以替代并发解决方案完全没有意义。我没有它的代码,如果我在里面,我可以想出一些替代代码工程解决方案来避免这种设置。我只是想知道一个线程在等待来自另一个线程的信号时是否可以以某种方式使用,以及为此使用什么同步机制。


更新

正如我上面提到的,我知道如何同步线程等。我只对我在这里介绍的情况感兴趣。 Mutexes, semaphores and locks 各种机制都会同步访问资源,同步事件顺序,同步各种并发问题,是的。但我对如何正确地做不感兴趣。我只是想知道是否可以使用之前描述的机制来解决这个问题。


更新 2

我似乎为那些自认为是并发专家的人打开了一个门户,让他们可以传送和讲授他们认为世界其他地方不知道线程是如何工作的。我只是问是否有针对这种情况的机制,而不是变通解决方案,不是 'the proper way to synchronise',也不是更好的方法。我已经知道我会做什么,而且永远不会处于这种虚构的境地。 纯属假设.

您对互斥量的典型使用方式存在误解。

如果你想做一些工作,你获取互斥锁来确定你需要做什么工作。您这样做是因为 "what work you need to do" 在决定​​需要完成什么工作的线程和将要完成工作的线程之间共享。但是随后您在执行工作时释放了保护 "what work you need to do" 的互斥量。

然后,当您完成工作时,您将获得互斥锁来保护您报告工作已完成。这是必需的,因为工作的状态与其他线程共享。您将该状态设置为 "done",然后释放互斥量。

请注意,没有线程会长时间持有互斥体,只是在微观的一秒钟内它需要检查或修改共享状态。因此,要查看工作是否完成,您可以获取保护该工作状态报告的互斥锁,检查状态,然后释放互斥锁。执行工作的线程不会持有该互斥量超过它需要更改该状态的一小部分秒。

如果您持有互斥锁的时间太长以至于您完全担心等待它们被释放,那么您要么做错了什么,要么以非常不典型的方式使用互斥锁。

所以使用互斥量来保护工作状态。如果需要等待工作完成,也可以使用条件变量。仅在更改或检查工作状态时保留该互斥锁。

But, If a thread attempts to acquire an already acquired mutex, that thread will be forced to wait until the thread that originally acquired the mutex releases it. So, while that thread is waiting, can it actually be usable. This is where my question is.

如果你考虑任何一个线程可能会减慢另一个线程的情况"waiting",那么你永远无法避免等待。所有必须发生的事情是一个线程访问内存,这可能会减慢另一个线程的速度。那你怎么办,从不访问内存?

当我们谈论一个线程"waiting"另一个线程时,我们的意思是等待线程完成实际工作。我们不担心线程间同步的微观开销,因为我们对此无能为力,而且它可以忽略不计。

如果您真的想找到一种方法使一个线程永远不会减慢另一个线程的速度,您将不得不重新设计我们使用线程的几乎所有内容。

更新:

例如,考虑一些具有互斥量和布尔值的代码。布尔值表示工作是否完成。 "assign work" 流程如下所示:

  1. 创建一个带有互斥量和布尔值的工作对象。将布尔值设置为 false。
  2. 分派一个线程来处理该对象。

"do work" 流程如下所示:

  1. 工作。 (这里没有互斥锁。)
  2. 获取互斥。
  3. 将布尔值设置为真。
  4. 释放互斥。

"is work done" 流程如下所示:

  1. 获取互斥。
  2. 复制布尔值。
  3. 释放互斥。
  4. 查看复制的值。

这允许一个线程执行工作,而另一个线程在执行其他操作时随时检查工作是否已完成。一个线程等待另一个线程的唯一情况是百万分之一的情况,即需要检查工作是否完成的线程恰好在工作刚刚完成的那一刻进行检查。即使在那种情况下,它通常会阻塞不到一微秒,因为持有互斥锁的线程只需要设置一个布尔值并释放互斥锁。即使这让您感到困扰,大多数互斥锁都有一个非阻塞 "try to lock" 函数(您将在 "check if work is done" 流程中使用它,以便检查线程 never 阻塞).

这是 正常 使用互斥锁的方式。实际争用是例外,而不是规则。

经过大量研究、思考和概览,我得出的结论是:

如果计算器可以帮我输入一系列 5 位数字,屏幕上会自动计算出它们的和。

不,它没有准备好这样的模式。但我仍然可以通过使用加号和最终等于按钮额外点击几下来获得总和。

如果我真的想要一个 thread 可以在监听某种条件的同时继续,我可以很容易地在 OS/kernel/SDK [=10] 周围实现个人 class 或对象=] 或其他任何东西并利用它。

• So at a low level, my answer is no, there is no such mechanism •

如果一个线程正在等待,那么它正在等待。如果它能继续执行那么它就不是真正的'waiting',在等待的并发意义上。否则这个状态会有一些其他术语(Alert Waiting,有人吗?)。这并不是说这是不可能的,只是不能使用类似于互斥锁或信号量等的一种简单的低级预定义机制。可以将所需的功能包装在某些 class 或对象等中

话说回来,有Interrupts and Interrupt handlers, which come close to addressing this situation. However, an interrupt has to be defined, with its handler. The interrupts may actually be running on another thread(不是说每个中断一个线程)。所以这里涉及到很多对象。