我是否需要 1 个读取器和 1 个写入器的互斥锁,我不介意丢失一些写入?

Do I need mutex for 1 reader and 1 writer where I don't mind losing some writes?

本文关键字:我不介意 读取 是否      更新时间:2023-10-16

我有一个运行两个线程的ROS节点,它们都共享同一个类。这个类有两组参数"要读"answers"要写",在控制循环中更新。有两种情况会出现问题。

我的程序是一个节点,将控制数据泵入四旋翼(案例1)并读取无人机数据以获得反馈(案例2)。在这里,我可以控制线程a的执行频率,并且我知道线程B可以与其读/写外部源通信的频率。

  1. 线程A从控制源读取数据并更新"to read"参数。线程B不断地读取这个"读取"参数,并将它们写入无人机源。我的观点是,我不介意,如果我错过了一些值A线程已经读取,但线程B可能碰巧读取的东西不是一个"真实"的值,因为线程A正在写或类似的东西?

  2. 线程B在写入"to read"参数后,读取将更新第二组"to write"的无人机的状态。再次,线程A需要读取这个"写入"参数,并将它们写回控制源,同样的方式,我不关心是否错过了一个值,因为我将得到下一个。

我需要一个互斥锁吗?或者读取线程只会错过一些值,但读取的值将是正确和一致的?

BTW:我使用boost:threads来实现线程B作为线程A,它是ROS节点本身。

数据竞争是未定义的行为。即使硬件保证了原子访问,甚至由于计时的原因,您的线程实际上也不会同时访问相同的数据。在c++中不存在良性的数据竞争。您可能很幸运,未定义的行为可以满足您的要求,但您永远无法确定,并且每次新的编译都可能破坏一切(不仅仅是遗漏的写入)。我强烈建议您使用std::原子。它很可能会生成几乎相同的代码,除了保证它总是工作。

一般来说,答案是需要锁或其他类型的同步机制。例如,如果您的数据是一个以空结束的字符串,那么您可以读取交错的数据。假设一个线程正在读取缓冲区,缓冲区中的字符串是"这是一个测试"。线程复制前四个字节,然后另一个线程进来,用"表兄弟,这是疯狂的"覆盖缓冲区。你最终会复制"这太疯狂了"。这只是可能出错的一个例子。

如果你总是复制原子类型,并且所有东西都是固定长度的,那么可以不受影响。但如果你这样做了,你的数据可能是不一致的。如果两个值应该是相关的,那么现在这种关系可能会被打破,因为您从以前的更新中读取了一个值,从新的更新中读取了一个值。

相关文章: