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

Multithreading 使线程等待条件,但允许线程在等待或侦听信号时保持可用,multithreading,synchronization,locking,busy-waiting,Multithreading,Synchronization,Locking,Busy Waiting,假设线程a必须将工作分派给线程B,那么是否有任何同步机制允许线程a不返回,但仍可用于其他任务,直到线程B完成,线程a才能返回 这不是特定于语言的,但是简单的c语言将是一个很好的选择 这可能完全违反直觉;这听起来确实如此,但我必须先问一下,然后再假设 请注意这是我感兴趣的虚构的假设情况。我不是在寻找现有问题的解决方案,所以其他并发解决方案完全没有意义。我没有它的代码,如果我在它,我可以想出一些替代的代码工程解决方案,以避免这种设置。我只是想知道在等待另一个线程的信号时,一个线程是否可以以某种方式使

假设线程a必须将工作分派给线程B,那么是否有任何同步机制允许线程a不返回,但仍可用于其他任务,直到线程B完成,线程a才能返回

这不是特定于语言的,但是简单的c语言将是一个很好的选择

这可能完全违反直觉;这听起来确实如此,但我必须先问一下,然后再假设

请注意
这是我感兴趣的虚构的假设情况。我不是在寻找现有问题的解决方案,所以其他并发解决方案完全没有意义。我没有它的代码,如果我在它,我可以想出一些替代的代码工程解决方案,以避免这种设置。我只是想知道在等待另一个线程的信号时,一个线程是否可以以某种方式使用,以及使用什么样的同步机制


更新

如上所述,我知道如何同步线程等。我只对我在这里介绍的情况感兴趣。互斥、信号量和锁各种机制都将同步对资源的访问,同步事件顺序,同步各种并发问题,是的。但是我对如何正确地做这件事不感兴趣。我只是虚构了这个情况,我想知道是否可以用前面描述的机制来解决这个问题


更新2


似乎我已经为那些认为自己是并行专家的人打开了一个门户,他们可以在偶然的机会传送和演讲他们认为世界上其他地方不知道线程是如何工作的。我只是问,对于这种情况,是否有一种机制,而不是一种变通解决方案,不是“正确的同步方式”,也不是一种更好的方式。我已经知道我会做什么,永远不会陷入这种虚构的境地这只是假设的

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

如果你想做一些工作,你需要获得互斥来确定你需要做什么工作。这样做是因为“您需要做什么工作”在决定需要做什么工作的线程和将要做什么工作的线程之间共享。但是,当你做工作时,你会释放互斥锁来保护“你需要做的工作”

然后,当您完成工作时,您将获得一个互斥锁,该互斥锁用于保护您的工作完成报告。这是必需的,因为工作状态与其他线程共享。将该状态设置为“完成”,然后释放互斥锁

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

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

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


但是,如果一个线程试图获取一个已经获取的互斥体,该线程将被迫等待,直到最初获取互斥体的线程释放它。因此,当该线程正在等待时,它是否可以实际使用。这就是我的问题所在

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

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

如果你真的想找到某种方式,一个线程永远不会,永远不会减慢另一个线程,你将不得不重新设计几乎所有我们使用的线程

更新:

例如,考虑一些具有互斥和布尔的代码。布尔值指示工作是否完成。“分配工作”流程如下所示:

  • 创建具有互斥和布尔值的工作对象。将布尔值设置为false
  • 分派线程处理该对象
  • “执行工作”流程如下所示:

  • 干活儿。(互斥锁不在此保留。)
  • 获取互斥
  • 将布尔值设置为true
  • 释放互斥锁
  • “完成工作”流程如下所示:

  • 获取互斥
  • 复制布尔值
  • 释放互斥锁
  • 看看复制的值
  • 这允许一个线程做工作,另一个线程在做其他事情时检查工作是否在任何时候完成。一个线程等待另一个线程的唯一情况是百万分之一的情况,即需要检查工作是否完成的线程恰好在工作刚刚完成时进行检查。即使在这种情况下,它通常也会阻塞不到一微秒,因为持有互斥体的线程只需要设置一个布尔值并释放互斥体。即使这让您感到困扰,大多数互斥锁都有一个非阻塞的“try to lock”函数(您可以在“check if work is done”流中使用该函数,这样检查线程就不会阻塞)

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