人们实际上使用什么无锁原语在c ++中进行无锁音频处理?

问题描述

任何进行过一些低级音频编程的人都被警告要锁定音频线程。 Here's一篇关于该主题的好文章

但是我仍然不清楚如何真正地使用c ++制作多线程音频处理应用程序,同时严格遵循此规则并确保线程安全。假设您正在构建像可视化器这样的简单对象。您需要将音频数据交给UI线程进行处理,并定期显示

我的第一个尝试是在两个缓冲区之间进行乒乓球。 buffer * _write_state是一个布尔类型,假定为原子型且无锁。 buffer *是某种类型的缓冲区,它不希望自己自己具有线程安全性,并且可以通过某种方式处理一个线程以不足的速率被调用的情况(在这里我并不打算陷入那种麻烦)。对于通用的布尔类型,实现如下所示:

// Write thread.
if (buffer1_write_state) {
  buffer1.write(data);
  if (buffer2_write_state) {
    buffer1_write_state = false;
  }
} else {
  buffer2.write(data);
  if (buffer1_write_state) {
    buffer2_write_state = false;
  }
}

// Read thread.
if (buffer1_write_state) {
  data = buffer2.read();
  buffer2.clear();
  buffer2_write_state = true;
} else if (buffer2_write_state) {
  data = buffer1.read();
  buffer1.clear();
  buffer1_write_state = true;
}

我已经使用std::atomic_flag作为我的布尔类型实现了这一点,并且据我的线程清理器所知,它是线程安全的。标准保证std :: atomic_flag是无锁的。令我感到困惑的是,要做到这一点,我还需要std :: atomic_flag的test()函数,该函数在c ++ 20之前是不存在的。可用的可变test_and_set()和clear()函数无法完成任务。标准不保证众所周知的替代方法std::atomic是无锁的。我听说大多数情况并非如此。

我读过一些线程,警告人们不要尝试自己尝试无锁结构,我很乐意遵守该技巧,但是如果没有基本工具,专家们将如何构建这些东西?保证没有锁吗?

解决方法

我听说大多数情况下不是。

您听错了。

std::atomic<bool> 在所有“常规” C ++实现中都是lock_free的,例如适用于ARM,x86,PowerPC等。如果atomic_flag的限制性API过多,请使用它。或std::atomic<int>,也普遍适用于具有无锁功能的目标上的lock_free。

(唯一合理的例外是8位计算机,无法加载/存储/ RMW一对字节。)


请注意,如果您以ARM为目标,则应启用编译器选项,以使您知道您不关心ARM CPU太旧而无法支持原子操作。在这种情况下,编译器将不得不在运行于ARMv4之类的 case 中编写使用库函数调用的慢速代码。参见std::atomic<bool> lock-free inconsistency on ARM (raspberry pi 3)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...