共享内存IPC同步(无锁)

问题描述 投票:12回答:2

请考虑以下情形:

需求:

  • Intel x64服​​务器(多个CPU插槽=> NUMA)
  • Ubuntu 12,GCC 4.6
  • 两个进程通过(命名的)共享内存共享大量数据
  • 经典的生产者-消费者方案
  • 内存被安排在一个循环缓冲区中(有M个元素)

程序顺序(伪代码):

过程A(生产者):

int bufferPos = 0;
while( true )
{
    if( isBufferEmpty( bufferPos ) )
    {
        writeData( bufferPos );
        setBufferFull( bufferPos );

        bufferPos = ( bufferPos + 1 ) % M;
    }
}

流程B(消费者):

int bufferPos = 0;
while( true )
{
    if( isBufferFull( bufferPos ) )
    {
        readData( bufferPos );
        setBufferEmpty( bufferPos );

        bufferPos = ( bufferPos + 1 ) % M;
    }
}

现在有一个古老的问题:如何有效地同步它们!?

  1. 使用互斥保护每个读/写访问权限
  2. 引入“宽限期”,以允许完成写入:当缓冲区(N + 3)被标记为已满(危险,但似乎可以正常工作...)时,读取缓冲区N中的数据。
  3. ?!?

理想情况下,我想要某种类似于内存屏障的东西,它可以保证所有CPU上都可以通过以下方式看到所有先前的读/写操作:

writeData( i );
MemoryBarrier();

//All data written and visible, set flag
setBufferFull( i );

这样,我只需要监视缓冲区标志,然后就可以安全地读取大数据块。

通常,我正在按照Preshing在这里描述的获取/释放范围寻找东西:

http://preshing.com/20130922/acquire-and-release-fences/

((如果我正确理解,C ++ 11原子仅适用于单个进程的线程,而不适用于多个进程。)

然而,GCC自己的内存屏障(肯定与__sync_synchronize结合编译器屏障asm volatile(“” :::“ memory”)似乎没有按预期的方式工作,因为在屏障之后可以看到写入,当我希望它们完成时。

任何帮助将不胜感激...

BTW:在Windows下,使用易失性变量(Microsoft特定的行为)可以正常工作...

c++ synchronization ipc shared-memory lock-free
2个回答
28
投票

Boost Interprocess支持共享内存。


0
投票

boost.lockfree数据结构对Boost.Interprocess具有基本支持。唯一的问题是无锁原子的阻塞仿真,在当前实现中不能保证该无进程间安全。所以boost.lockfree仍然不是进程间安全的,对吧?

© www.soinside.com 2019 - 2024. All rights reserved.