具有单个生产者单一使用者的无锁循环缓冲区
Lockless circular buffer with single producer singular consumer
我有一个永不锁定或分配内存的使用者线程,以及一个可以锁定和分配内存的生产者线程。 我想实现一个两位循环缓冲区,以便能够从生产者向消费者线程提供数据,并且绑定的是,只要没有新数据可供使用,消费者只需重用已经可用的数据。
这就是我现在想出的:
bool newDataAvailable = false;
bool bufferEmpty = true;
foo* currentData = new foo();
foo* newData = new foo();
void consumer() {
while(true) {
currentData->doSomething();
if(newDataAvailable) {
foo* tmp = currentData;
// Objects are swapped so the old one can be reused without additional allocations
currentData = newData;
newData = tmp;
newDataAvailable = false;
bufferEmpty = true;
}
}
}
void producer() {
while(true) {
while(!bufferEmpty) { wait(); }
newData->init();
bufferEmpty = false;
newDataAvailable = true;
}
}
这种幼稚的实现可以吗?我知道读取和写入变量可以是非原子的,所以我应该使用原子存储,但这些可能会导致锁定。这里是否需要使用原子存储? 另外,我想消除生产者中的主动等待,我认为我可以使用std::condition_variable
,但它们需要使用互斥体,我负担不起。
编写共享变量而不使用互斥锁的多线程代码很难正确。 请参阅无锁编程简介、无锁缓冲区。
如果您绝对必须避免使用互斥锁,那么我强烈建议您使用预制的无锁队列,例如 Boost.lockfree 或 MPMCQueue 作为轻量级的非助推替代方案。
我知道读取和写入变量可以是非原子的,所以我应该使用原子存储,但这些可能会导致锁定。
对于所有基元类型(不超过 CPU 的本机大小),std::atomic
通常是无锁的(不使用互斥锁)。 您可以通过调用std::atomic<T>::is_lock_free
来检查std::atomic
是否会对给定类型使用互斥锁
这里是否需要使用原子存储?
是的,绝对。您要么需要使用互斥体,要么需要使用原子组学。
另外,我想消除生产者中的活动等待,我认为我可以使用std::condition_variable
当您无法使用互斥锁时,您唯一的选择就是使用旋转锁。 如果上下文中允许这样做,则可以在旋转锁中使用std::this_thread::yield()
来减少 CPU 负载。(但是互斥锁可能会更快)
编辑: 只有 2 个原子的潜在解决方案是:
std::atomic<foo*> currentData = new foo();
std::atomic<foo*> newData = new foo();
void consumer() {
foo* activeData = currentData;
while (true) {
activeData->doSomething();
foo* newItem = currentData;
if (newItem != activeData) {
newData = activeData;
activeData = newItem;
}
}
}
void producer() {
while (true) {
foo* reusedData = newData;
if (!reusedData)
continue;
newData = nullptr;
reusedData->init();
currentData = reusedData;
}
}
- 如何循环打印顶点结构
- 如何在C++中从两个单独的for循环中添加两个数组
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 正在尝试了解输入验证循环
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 循环后如何继续阅读
- 有没有办法重复循环循环?
- Qt有循环缓冲吗?
- 虽然第三次循环循环,尽管在我眼中没有满足它的条件,因此打印了一个空字符串
- 避免以不同的迭代剂的循环循环避免几乎相同的代码重复
- 循环循环保存到数组,然后访问;
- 未定义的行为怪癖:在缓冲区外读取导致循环永远不会终止
- 对于循环循环仅 3 次
- 处理媒体循环循环循环通过向量中的对象的各个方面
- 将C转换为循环循环循环
- 关于如何正确循环循环并找到最小的价值,需要基本C 的帮助
- 我如何循环循环switch语句检查重新检查char?(C )
- 在嵌套循环/循环不变量中检查一次
- 只有在充满for循环的情况下才能进行开放缓冲播放
- 调用linearize后奇怪的boost循环缓冲行为