在串行代码中,更新最大值可以简单地通过
template<typename T>
void update_maximum(T& maximum_value, T const& value) noexcept
{
if(value > maximum_value) maximum_value = value;
}
Run Code Online (Sandbox Code Playgroud)
但是,如何对atomic<T>
保存最大值的变量执行此操作:
template<typename T>
void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept
{
// want a lock-free, thread-safe implementation
}
Run Code Online (Sandbox Code Playgroud)
显然,串行版本的代码不起作用,因为另一个线程可能maximum_value
在加载和存储之间发生变化.可以使用compare_exchange
(比较==
而不是>
)来实现这个吗?怎么样?
请注意,不允许显式锁定(允许的唯一锁定是执行时可能出现的锁定std::atomic<T>
).
我想使用原子比较和交换,但不是等于,我想只在内存位置不等于旧值时进行交换.在C中有可能吗?
我必须从多播(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
该序列号之前),我将基本上在我的系统中两次使用相同的数据包.有什么方法可以克服这种情况?