“融合”2个静音线程为1,以便在单核上执行

时间:2012-07-31 07:06:12

标签: c++ multithreading mutex

此 这是一个奇怪的问题,所以我试着提供长篇解释    让我们说你在一台核心机器上运行。你有2个线程,让我们说使用互斥体的经典生产者消费者问题。现在我想知道什么时候在单核机器上运行(所以1核没有HT):
在C ++中是否有一种方法可以将这两个线程的执行融合为一个,这样互斥可以实现为一个简单的int存储/加载操作,而不是静音。 例如,这会工作: 统一线程中的生产者代码可以只是将内容放入循环缓冲区,如果当前buffer_idx高于processed_idx,则消费者代码将只从缓冲区中读取。

我知道这似乎是一个愚蠢的问题,但是很多嵌入式内容仍然是1核心。 为简单起见,假设两个线程都是

形式
while(! shutdown)
{
//...
}

只是按照预期将两个身体同时放在一起吗?

4 个答案:

答案 0 :(得分:1)

您可以将生产者和消费者都放在一个线程中。但是为了什么?它们的存储/加载操作将按顺序执行。他们之间总会有“和平”(不包括意外情况)。对于每个生产者商店操作,将有消费者加载操作(如果没有条件语句,如果是,则生产者将停止并等待消费者代码将加载所有东西,然后循环再次启动)。 IMO,使用这种模型,您只能在代码中描述一小部分真实情况。

编辑:即使您使用的是单核计算机,将逻辑拆分为多个线程也会使您获得比在一个线程中创建所有内容更好的性能。例如,虽然生产者会创建一些东西,但即使存储了一些东西,你的消费者也什么都不做,这是时间的浪费。想象一下,在消费者加载之后,他必须把东西给你逻辑的另一个元素,如果有很多其他元素,站在消费者之后,他们都只等待一个逻辑元素 - 生产者,然后等待处理器在大多数时间内在线程之间切换所花费的时间少于生产或消费东西所需的时间。

答案 1 :(得分:0)

因为通过一个接一个的无限循环意味着一个永远不会被执行,让我们假设我们有“神奇的”GOTO语句,每次都将我们跳到正确的位置。然后是的,将两个while循环放在一起可能会起作用,因为GOTO本质上是一个监视器,虽然它可能不是你想要的。

另一方面,假设循环在正确的时间终止。将两个线程(没有切断CPU时间)融合为一个基本上会使您的初始问题无效。不需要互斥锁,因为没有什么可以排除而不是运行过程本身。

另外要考虑的是单核系统也存在并发问题,它们在时间片中运行多个线程来模拟(在某种程度上)多核系统的工作方式;相同的multexing东西应该可以直接转让。

答案 2 :(得分:0)

你仍然必须小心谨慎。它不能同时运行两个线程,但是通过premptive多任务处理,您的代码可以被中断,而另一个线程可以在任何时候运行,因此您仍然需要锁定一般情况。

一个常见的事情是在第一个线程上进行“存储队列”操作,而不是直接在另一个线程中调用“队列中的进程”函数(并且只有一个线程)。通过正确的设计,可以使代码在单个内核上运行单线程,并且如果您有多个内核,则可以使用多线程。这样可以避免在只有一个核心时锁定。

答案 3 :(得分:0)

这种“未受保护”的队列在嵌入式内容中很常见,例如。在线程和中断驱动程序之间进行通信。这样的驱动程序根本不能使用互斥锁(尽管它们通常可以发信号通知信号量以使线程准备好,例如,当已完成的协议数据包被推到这样一个未受保护的队列上时)。驱动程序通信的优点是一端绝对确保另一端不能中断它 - 驱动程序不能被线程中断。这使得确保索引/指针以“安全”顺序更新相当容易。

然而,在两个线程之间,事情变得更加困难。当索引/指针被操纵时,任何一端都可以在任何点被另一端中断。我总是使用互斥锁来锁定这些队列,(我用于emebedded通信的线程间队列无论如何都没有内部存储 - 消息本身有一个内部前向链接,这使得无锁队列更加尴尬)。