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

时间:2018-12-18 23:24:24

标签: multithreading synchronization locking busy-waiting

考虑到线程A必须将工作分配给线程B的情况,是否存在任何同步机制,允许线程A不返回,但仍可用于其他任务,直到线程B完成,线程A可以返回哪一个?

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

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

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


更新

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


更新2

似乎我已经为那些认为自己是并发专家的人们打开了门户,他们偶然地进行演讲和演讲,他们认为世界其他地方不知道线程是如何工作的。我只是问是否有一种针对这种情况的机制,不是围绕解决方案的解决方案,不是“正确的同步方式”,不是更好的同步方式。我已经知道我会怎么做,永远不会陷入这种局面。 这仅仅是假设性的

2 个答案:

答案 0 :(得分:-1)

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

如果您想做一些工作,则可以获取互斥量来确定需要做的工作。之所以这样做,是因为“决定您需要做什么”的线程在决定需要完成哪些工作的线程与将要执行该工作的线程之间共享。但是随后,您将释放互斥量,以保护您在工作时“需要做的工作”。

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

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

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

因此,请使用互斥量来保护作品的状态。如果您需要等待工作完成,请使用条件变量。仅在更改或检查作品状态时按住该互斥锁。

  

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

如果您考虑某个线程可能使另一个线程变慢而处于“正在等待”的情况,那么您将永远无法避免等待。所要做的就是一个线程访问内存,这可能会减慢另一个线程的运行速度。那你怎么办,永远不要访问内存?

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

如果您确实想找到某种方式,一个线程永远不会降低另一个线程的速度,那么您将不得不重新设计几乎所有我们用于线程的东西。

更新:

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

  1. 创建一个具有互斥量和布尔值的工作对象。将布尔值设置为false。
  2. 调度线程以对该对象进行处理。

“完成工作”流程如下:

  1. 工作。 (互斥量不在此处。)
  2. 获取互斥锁。
  3. 将布尔值设置为true。
  4. 释放互斥锁。

“工作已完成”流程如下:

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

这使一个线程可以工作,而另一个线程可以在做其他事情的同时随时检查工作是否完成。一个线程等待另一个线程的唯一情况是百万分之一的情况,其中一个需要检查工作是否完成的线程恰巧在工作刚刚完成时立即进行检查。即使在那种情况下,由于持有互斥锁的线程只需要设置一个布尔值并释放互斥锁,它通常将阻塞不到一微秒。而且即使令您烦恼的是,大多数互斥体也具有无阻塞的“尝试锁定”功能(您将在“检查工作是否完成”流程中使用该功能,以使检查线程从不阻塞)

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

答案 1 :(得分:-1)

经过大量研究,思考和概述,我得出的结论是,它就像在问:

如果计算器具备我的能力,只需输入一系列5位数字并自动在屏幕上获取其总和即可。

否,它还没有准备好这种模式。但是我仍然可以通过使用加号和最终等于按钮的几次点击获得总和。

如果我真的想要一个thread可以在侦听某种条件时继续运行,那么我可以轻松地在OS /内核/ SDK thread周围实现一个个人类或对象,然后制作的使用。

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

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

话虽如此,有Interrupts and Interrupt handlers,正好可以解决这种情况。但是,必须使用其处理程序定义一个中断。中断实际上可能是running on another thread(不是每个中断一个线程)。因此,这里涉及许多对象。

相关问题