c++ - 在 C++11 中安全明确地操作原子变量

标签 c++ multithreading c++11 atomic stdatomic

我必须从多播 (UDP) 流中读取一些数据(速度惊人 - 每秒高达 5000 条消息)。因为流是多播的(并且数据非常关键),数据提供者提供了两个发送相同数据的流(他们的逻辑是在两个流中丢弃相同数据包的可能性非常接近于零)。所有数据包都标有序列号以进行跟踪。

此外,该应用程序的时间非常关键,以至于我不得不同时收听两个流并从最先接收到的多播流中获取下一个序列号 - 当相同的数据包出现在镜像流中时,我简单地放下它。

我计划在两个函数之间使用一个公共(public)的“sequence_number”变量来实现这个删除功能——顺便说一下,这两个函数在不同的线程中运行。序列号是 atomic 因为它将从两个不同的线程读取和更新。

想到的明显算法是

if (sequence number received from the stream > sequence_number)
{
   process packet;
   sequence_number = sequence number received from the stream;
}

(上面的算法需要在序列号乱序的时候修改 - 它们可以因为它是一个 UDP 流 - 但我们暂时忘记它)

我的问题是:

从我 std::load 我的 sequence_number 开始,检查它是否小于我从流中收到的序列号,接受数据包,并且 < em>最后 std::store 新的序列号到sequence_number;如果另一个流接收到相同的数据包(具有相同的序列号)并执行相同的操作(在第一个流在该序列号上完成 std::store 之前),我将最终得到我的系统中有两次相同的数据包。有什么方法可以克服这种情况?

最佳答案

不要把处理无序数据包的问题推迟到以后,因为解决这个问题也为同步线程提供了最优雅的解决方案。

数组的元素是用于数据竞争目的的唯一内存位置。如果您根据其序列号将每个数据包(通过指针写入原子地)放入不同的数组元素中,您将摆脱大部分争用。还使用 compare-exchange 来检测其他线程(其他流)是否已经看到该数据包。

请注意,您不会有通常与比较交换相关联的重试循环,或者您拥有数据包的第一个拷贝并且比较交换成功,或者数据包已经存在并且您的拷贝可以被丢弃。所以这种方法不仅是无锁的,而且是无等待的:)

关于c++ - 在 C++11 中安全明确地操作原子变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24842932/

相关文章:

c++ - 没有返回类型的 main 的使用在 C++11 中被淘汰了吗?

c++ - 使用 boost::regex 的正则表达式问题

c++ - Qt - 帮助链接动态库

android - Android 中的处理程序逻辑

java - 如何在部署 liferay portlet 之前杀死所有线程

c++ - 如何修复 istringstream 编译器错误?

c++ - 在空指针上调用 allocator_traits::deallocate

c++ - 在qt中创建一个qstate

java - 在调试时如何直观地表示哪些线程锁定了 Java 中的哪些对象?

c++ - push_back() "new"一个对象在添加到 c++ 中的 std::list 之前