在持有boost :: interprocess :: scoped_lock时睡眠会导致它永远不会被释放

Ped*_*ino 2 c++ linux mutex ipc boost-interprocess

我做IPC Linux的使用boost::interprocess::shared_memory_object按照基准(匿名互斥体示例).

有一个服务器进程,它创建shared_memory_object并写入它,同时保持interprocess_mutex包裹在scoped_lock; 和客户端进程打印其他人写的任何内容 - 在这种情况下,它是一个int.

我遇到了一个问题:如果服务器在持有互斥锁的情况下休眠,则客户端进程永远无法获取它并永远等待.

越野车服务器循环:

using namespace boost::interprocess;
int n = 0;
while (1) {
    std::cerr << "acquiring mutex... ";
    {
        // "data" is a struct on the shared mem. and contains a mutex and an int
        scoped_lock<interprocess_mutex> lock(data->mutex);
        data->a = n++;
        std::cerr << n << std::endl;
        sleep(1);
    } // if this bracket is placed before "sleep", everything works
}
Run Code Online (Sandbox Code Playgroud)

服务器输出:

acquiring mutex... 1
acquiring mutex... 2
acquiring mutex... 3
acquiring mutex... 4
Run Code Online (Sandbox Code Playgroud)

客户端循环:

while(1) {
   std::cerr << "acquiring mutex... ";
   {
      scoped_lock<interprocess_mutex> lock(data->mutex);
      std::cerr << data->a << std::endl;
   }
   sleep(1);
}
Run Code Online (Sandbox Code Playgroud)

客户端输出(永远等待):

acquiring mutex...
Run Code Online (Sandbox Code Playgroud)

问题是,如果我在sleep通话前将支架移动到线路,一切正常.为什么?我不认为用锁定的互斥锁睡觉会导致互斥锁被永久锁定.

我唯一的理论是,当内核唤醒服务器进程时,作用域结束并释放互斥锁,但等待进程没有机会运行.服务器然后重新获得锁...但这似乎没有多大意义.

谢谢!

Ste*_*sen 7

你的理论是正确的.

如果你查看你链接的引用中的匿名互斥示例的底部,你会看到

我们可以看到,互斥锁对于保护数据非常有用,但不会向另一个进程通知事件.

释放互斥锁并不会通知可能正在等待它的任何其他人,并且由于您的进程刚刚醒来,它几乎肯定有足够的调度量来做更多的工作.它会在它再次休眠之前循环并重新获取互斥锁,这是客户端获取互斥锁本身的第一次机会.

将服务器移到sleep()范围之外意味着它在互斥锁空闲时进入休眠状态,使客户端有机会自行运行并获取互斥锁.

sched_yield()如果您想放弃处理器,请尝试调用(仅限Linux),但仍在您的范围内.sleep(0)也可以工作.