Bur*_*tto 5 c# parallel-processing concurrency multithreading multiprocessing
我有一个相对简单的案例:
棘手的部分是更新需要“原子地”发生,这样它就不会从本地状态读取,例如,只写入了一半的更新。状态不限于使用原语,并且可以包含任意类 AFAICT atm,因此我无法通过使用Interlocked原子操作之类的简单方法来解决它。我计划在其自己的线程上运行每个任务,因此在本例中总共有两个线程。
为了实现这个目标,我想使用双缓冲区技术,其中:
这是这个想法的总体要点,但实际的实现当然会有点不同。
我试图查找这是否是一个常见的解决方案,但找不到太多信息,所以这让我想知道以下内容:
我几乎觉得我已经走进了一个死胡同,我找不到(因为我不知道要搜索什么)更多的资源和信息来看看这种方法是否“好”。我计划用 .NET C# 编写此内容,但我认为这些技术和解决方案可以转换为任何语言。所有见解均受到赞赏。
您实际上需要四个缓冲区/对象。两个缓冲区/对象由读者拥有,一个由作者拥有,另一个在邮箱中。
读者 - 每次他在新对象上完成一组原子操作时,他都会使用互锁交换将旧对象句柄(指针或索引无关紧要)与邮箱对象句柄交换。然后,他查看新获得的对象,并将序列号与他刚刚读取(并且仍然持有)的对象进行比较,以找出哪个对象更新。
写入者将最新数据的完整副本写入他的对象,然后使用互锁交换将他新写入的对象与邮箱对象交换。
正如您所看到的,写入者可以随时窃取邮箱对象,但绝不能窃取读取者正在使用的邮箱对象,因此读取操作保持原子性。读者可以随时窃取邮箱对象,但绝不能窃取作者正在使用的邮箱对象,因此写入操作保持原子性。
只要互锁交换函数生成正确的内存栅栏(为写入线程中完成的交换释放,为读取线程获取),对象本身可以是任意复杂的。