首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >任意大小的数据/向量/数组的原子和无锁写入

任意大小的数据/向量/数组的原子和无锁写入
EN

Stack Overflow用户
提问于 2020-10-01 00:26:46
回答 1查看 100关注 0票数 1

我正在尝试实现以下功能:

  • 具有任意大小的数据类型的原子和无锁的写入或读-修改-写入(在我的例子中,通常是包含最多6个元素的浮点/int向量)。
  • 从上述数据类型读取的原子数据类型,不阻止写入线程。读取操作可以被写入操作阻止。

Usecase:我正在为数控机床编写软件。电机的步进脉冲是在实时线程中在软件中生成的。这个实时线程不断更新一个保持轴当前位置的变量。多个其他非实时线程可以读取该变量,例如显示当前位置。

问题1:对于这类问题是否有标准/公认的解决方案或模式?

我想出了以下想法:使用std::atomic<uint64_t>保护线程当前正在写入的数据和跟踪天气(通过检查最后一个位)或从读取开始就已经写入(通过增加写入的值)。

代码语言:javascript
复制
template <class DATA, class FN>
void read_modify_write(DATA& data, std::atomic<uint64_t>& protector, FN fn)
{
  auto old_protector_value = protector.load();
  do
  {
    // wait until no other thread is writing
    while(old_protector_value % 2 != 0)
      old_protector_value = protector.load();

    // try to acquire write privileges
  } while(!protector.compare_exchange_weak(old_protector_value, old_protector_value + 1));

  // write data
  data = fn(data);

  // unlock
  protector = old_protector_value + 2;
};

template <class DATA>
DATA read(const DATA& data, std::atomic<uint64_t>& protector)
{
  while(true)
  {
    uint64_t old_protector_value = protector.load();

    // wait until no thread is writing
    while(old_protector_value % 2 != 0)
      old_protector_value = protector.load();

    // read data
    auto ret = data;

    // check if data has changed in the meantime
    if(old_protector_value == protector)
      return ret;
  }
}

问题2:上述代码线程安全并满足上述要求吗?

问题3:可以改进吗?

(我能找到的唯一理论问题是,如果计数器环绕,即在1读操作期间执行2^63写入操作。如果没有更好的解决方案,我认为这个弱点是可以接受的。)

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-01 12:51:46

严格地说,您的代码不是无锁的,因为您有效地使用protector的LSB实现自旋锁。

您的解决方案看起来非常像一个序列锁。然而,实际的读取操作auto ret = data;严格来说是一种数据竞争。公平地说,在C++17中编写完全符合标准的seqlock是不可能的,因为我们必须等待C++20。

可以扩展seqlock,使读取操作无锁,而代价是更高的内存使用量。其思想是拥有多个数据实例(让我们将它们称为时隙),并且写操作总是以循环方式写入下一个插槽。这允许读取操作从最后一个完全写入的槽中读取。德米特里·维尤科夫( Dmitry )在改进的无锁SeqLock中描述了他的做法。您可以看看我的seqlock实现,它是我xenium库的一部分。它还允许使用可配置的槽数进行无锁读取操作(尽管它与Vyukov在找到最后一个完整写入的插槽方面略有不同)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64147529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档