如何在实时应用程序中锁定线程[关闭]

Posted

技术标签:

【中文标题】如何在实时应用程序中锁定线程[关闭]【英文标题】:How to lock threads in real-time applications [closed] 【发布时间】:2018-10-06 10:08:30 【问题描述】:

这里绝对是多线程新手。

我有一个播放音乐的多媒体应用程序。具体来说,它有一个读取一些数据的音频线程 - 例如一个波形 - 并将其发送到声卡。这是一个实时操作,因此必须以“非阻塞”方式尽快执行。

另一方面,还有另一个线程负责处理用户界面。在这里,用户可以对该数据执行一些操作 - 例如通过添加或删除块来修改波形。这当然应该是可能的,但音频线程必须保持不受干扰地运行,并且始终提供可用的数据。

我的第一个想法是这样的(c++-ish pthread 伪代码):

音频线程:

vector<sample> samples; // this is shared between this thread and the UI thread
mutexLock();
for (Sample sample : samples)
    play(sample);
mutexUnlock();

还有 UI 线程:

void onEditSample()

    while (mutexTryLock() == 0)
    
        editSamples(samples);
        mutexUnlock();
        break;
    

但我不太确定 try-lock 部分。您认为处理此问题的最佳方法是什么?

【问题讨论】:

您可能想研究标准Thread support library 的类和特性。由于您的问题过于宽泛,无法为您提供简洁的建议,这将有助于未来的研究人员解决您的问题。 @πάνταῥεῖ 我喜欢标准库中的线程。但是我现在有点坚持使用 pthreads。反正基础理论应该是一样的吧? 如果您不能使用当前的 c++11 标准库,我建议您为底层 pthreads 函数编写包装类。你可以很容易地想出相同的接口,所有的原则(尤其是使用 RAII 和锁守卫都是一样的)。 您可能希望将要在小缓冲区负载中播放的波形发送到音响系统,只锁定波形以复制每个缓冲区。还使用播放线程的读锁和波形编辑线程的写锁,但在完成编辑后准备好被复制到共享波形上。 【参考方案1】:

首先,在 UI 线程中循环使用 Try Lock 是没有意义的。只是一个普通的锁就可以了——它会阻塞的唯一线程是 UI 线程,而不是正在播放的线程。

现在,

这是一个实时操作,因此必须尽快执行 可能以“非阻塞”方式。

这并不完全正确。它不需要尽可能快速 执行 - 它需要在一定的及时性限制内执行。 (必须在声音设备播放完最后一组样本之前提​​供新样本 - 必须遵守最后期限)。

因此,鉴于互斥锁将在 UI 线程更新样本时锁定音频线程,我们所拥有的是音频线程不能被阻塞太久,因此 UI 线程必须只持有互斥锁很短的时间。

要尽量减少 UI 线程持有互斥锁的时间,您必须尽量减少更新样本所需的工作量。一种方法是使用 双缓冲 - 您有两个样本向量,其中一个由指针指示的音频线程积极使用。当 UI 线程想要更​​新样本时,它会将新样本复制到非活动向量中(没有持有互斥锁),然后获取互斥锁,将指针值交换到另一个向量,然后解锁互斥体。然后,互斥锁仅在更新单个指针值所需的时间长度内保持,这非常短。

【讨论】:

很好的解释,特别是对于双缓冲技巧(我不知道)。您写道“它要阻塞的唯一线程是 UI 线程,而不是正在播放的线程”。怎么会?是因为双缓冲优化吗? @Ignorant: 不,我的意思是如果在 UI 线程中调用 try 锁并返回错误而不阻塞(因为互斥锁已被另一个线程持有),那么唯一的线程 会阻塞的是 UI 线程。 try 锁只对调用线程有帮助,并且只有当该线程有其他事情时它才有用,无论如何它可以在没有互斥锁的情况下有用。

以上是关于如何在实时应用程序中锁定线程[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

再次运行应用程序时如何停止关闭的应用程序留下的线程? C#

如何根据检测到颤振应用程序中的锁定或关闭屏幕采取行动

分析多线程程序 [关闭]

如何阻止我的 UI 线程锁定?

如何读取锁定多线程 C++ 程序

销毁全局对象[关闭]