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

Cha*_*ani 5 c++ multithreading atomic c++11 stdatomic

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

此外,应用程序时间也是很重要的,我不得不听并行两个流并拿起从哪个组播流它是在第一次收到一个序列号 - 当同一包是上镜的流,我只需将它.

我计划在两个函数之间使用一个通用的"sequence_number"变量实现这个drop特性 - 顺便说一下,它在不同的线程中运行.序列号是atomic从两个不同的线程中读取和更新的序列号.

想到的明显算法是

if (sequence number received from the stream > sequence_number)
{
   process packet;
   sequence_number = sequence number received from the stream;
}
Run Code Online (Sandbox Code Playgroud)

(上面的算法需要在序列号出现故障时修改 - 它们可以是UDP流 - 但暂时忘记它)

我的问题是:

从时间我std::load我的sequence_number,检查它是否比我从流接收的序列号更小,接受数据包,并最终 std::store在新的序列号sequence_number; 如果另一个流接收到相同的数据包(具有相同的序列号)并执行相同的操作(在第一个流完成std::store该序列号之前),我将基本上在我的系统中两次使用相同的数据包.有什么方法可以克服这种情况?

Ben*_*igt 2

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

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

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