-1

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

这不是特定于语言的,但简单的 c 语言将是对此做出回应的绝佳选择。

这可能是绝对违反直觉的。听起来确实如此,但我必须在假设之前先问一下……

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


更新

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


更新 2

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

4

2 回答 2

-1
于 2018-12-19T03:55:20.957 回答
-1

您对通常如何使用互斥锁存在误解。

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

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

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

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

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

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

如果您考虑一个线程可能会减慢另一个线程“等待”的任何情况,那么您永远无法避免等待。所要做的就是一个线程访问内存,这可能会减慢另一个线程的速度。那你怎么办,从不访问内存?

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

如果你真的想找到一种方法,一个线程永远无法减缓另一个线程的速度,你将不得不重新设计我们使用线程的几乎所有东西。

更新:

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

  1. 使用互斥锁和布尔值创建一个工作对象。将布尔值设置为 false。
  2. 调度一个线程来处理该对象。

“做工作”流程如下所示:

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

“工作完成”流程如下所示:

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

这允许一个线程做工作,另一个线程检查工作是否在它想做的任何时候完成,同时做其他事情。一个线程等待另一个线程的唯一情况是百万分之一的情况,其中需要检查工作是否完成的线程恰好在工作刚刚完成的那一刻进行检查。即使在这种情况下,它通常也会阻塞不到一微秒,因为持有互斥锁的线程只需要设置一个布尔值并释放互斥锁。即使这让您感到困扰,大多数互斥锁都有一个非阻塞的“尝试锁定”功能(您将在“检查工作是否完成”流程中使用它,以便检查线程永远不会阻塞)。

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

于 2018-12-19T01:08:47.090 回答