在线程争用下等待的最快方法

Posted

技术标签:

【中文标题】在线程争用下等待的最快方法【英文标题】:Fastest method to wait under thread contention 【发布时间】:2012-01-20 21:01:18 【问题描述】:

我在 Linux 上使用 pthread。我有一个循环缓冲区来将数据从一个线程传递到另一个线程。也许循环缓冲区不是在这里使用的最佳结构,但改变它不会让我的问题消失,所以我们将它称为队列。

每当我的队列已满或为空时,pop/push 操作都会返回 NULL。这是有问题的,因为我的线程会定期触发。等待另一个线程循环会花费太长时间。

我尝试过使用信号量 (sem_post, sem_wait),但在争用下解锁最多需要 25 毫秒,这与我的循环速度差不多。我试过用 pthread_cond_t 等待,但解锁需要 10 到 15 毫秒。

我可以使用更快的机制来等待数据吗?

编辑*

好的,我使用了条件变量。我使用的是嵌入式设备,因此不能选择添加“更多内核或 CPU 功率”。这让我意识到我已经设置了各种各样的线程优先级,所以我会在继续之前解决这个问题

【问题讨论】:

您必须要么严重滥用这些同步功能,要么严重错误测量它们的行为才能找到这些时间。条件变量几乎是你能做的最好的,它们几乎是瞬时的。你是如何使用它们的,可能更重要的是,你是如何测量的? 我正在使用clock_gettime(CLOCK_REALTIME, &time) 来测量,在释放锁之前和之后 您是否偶然在执行 I/O 记录的同一行/函数调用中获得结束时间? @Eric 这只是衡量你的线程再次获得 CPU 的时间。这并不能衡量释放锁需要多长时间。您可能拥有比核心更多的准备运行线程,并且在这 25 毫秒内,运行了一些其他线程。 (您可以通过测量优先级高于其他所有线程的线程来确认这一点。) 如果您处理循环需要 25 毫秒,那么您使用什么同步机制来管理数据队列应该无关紧要,(假设该机制有效,即不会 CPU 循环,不会错过推/弹出)。锁定释放时间、interlockedBlahBlah、信号量调用、condvar 等待/信号、上下文更改等只是 25 毫秒内的一点噪音。我假设您在队列中推送/弹出指针/实例,而不是复制输入/输出大型结构? 【参考方案1】:

您应该使用条件变量。唯一更快的方法是特定于平台的,而且速度快得可以忽略不计。

您看到您认为性能不佳的原因仅仅是因为您的线程被取消调度。当您的线程接近其时间片的末尾并且调度程序允许未阻塞的线程抢占正在运行的线程时,您会看到很长的“延迟”。如果您的核心多于线程或将线程设置为更高的优先级,您将不会看到这些延迟。

但这些延迟实际上是一件好事,您不必担心它们。其他线程也有机会运行。

【讨论】:

时间段与锁无关。锁在毫秒的前几分之一被释放。另一次是线程没有运行,因为系统正在做其他事情。 David +1 - 盒子超载了。需要更多内核(可能更多 RAM)、更少 CPU 密集型应用程序。比利也 +1 - 25us,更不用说毫秒,对于锁定释放来说太长了。

以上是关于在线程争用下等待的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

JVM 问题排查

多线程的交互

动态内存分配的线程争用

当大多数类并发时如何找出java中的争用问题

从多个线程写入内存区域会导致争用吗?

C++ / Windows:HeapAlloc() 用于无争用的每线程堆