【问题标题】:Mutex doesn't synchronize C++互斥锁不同步 C++
【发布时间】:2017-11-10 22:49:45
【问题描述】:

我有 2 个进程。第一个向另一个发送一些数据,同步每个动作。 它实际上发送数据如下:

 Process : A sends 1
 Process : B receives 1
 Process : A sends 2
 Process : B receives 2

问题是,当我运行进程 A 时,它会从头开始发送所有数据,然后我看到如下内容:

 Process : A sends 1
 Process : A sends 2
 Process : A sends 3
 Process : B receives 3

我做了如下:

  Process A
   HANDLE mutex;    
    mutex = CreateMutex(NULL, FALSE, TEXT("mutex1"));
    if (mutex == INVALID_HANDLE_VALUE) {
        _tprintf(TEXT("Create mutex error !.\n"), GetLastError());
        return 1;
    }
   for (int i = 0; i < sender_length;i++) {
       WaitForSingleObject(mutex,INFINITE);
       sendToB(data);
       ReleaseMutex(mutex);
       }

     CloseHandle(mutex);

B 流程如下:

 Process B:

  HANDLE mutex;

    mutex = OpenMutex(SYNCHRONIZE, FALSE, TEXT("mutex1"));

    if (mutex == INVALID_HANDLE_VALUE) {
        _tprintf(TEXT("Mutex error ! \n"), GetLastError());
        return 1;
      }
     for (int i = 0; i < sender_length;i++) {
           WaitForSingleObject(mutex,INFINITE);
           receiveFromA(data);
           ReleaseMutex(mutex);
           }

         CloseHandle(mutex);

【问题讨论】:

  • 不要在您尝试同步的代码中创建互斥锁。
  • 您的互斥锁心智模型似乎存在严重错误。除了告诉您互斥锁并没有像您认为的那样做之外,这里实际上没有可以回答的问题。
  • 互斥锁只是说一次只能容纳一个东西。它没有说明各种参与者获得它的顺序。你所描述的是一个完全有效的结果。您可能想要某种队列。
  • 或者改用可等待事件。 A 可以在发送数据时发出一个事件信号,B 可以在接收之前等待该事件。然后A 可以等待B 在收到数据后发出另一个事件的信号,然后再发送新数据。
  • 你在标题中有 C++,但你标记为 C。这是你想要的吗?

标签: c winapi concurrency mutex


【解决方案1】:

我不确定这是你的问题,但我认为它很有可能至少是一个贡献者:Windows 锁已经有一段时间不公平了。有关详细信息,请参阅 Joe Duffy 的文章 Anti-convoy locks in Windows Server 2003 SP1 and Windows Vista

Duffy 专门针对互斥体说以下(我添加的突出显示):

当然,Windows 锁仍然有点公平。互斥锁的等待列表按 FIFO 顺序保存,操作系统总是唤醒位于此类等待队列前面的线程。 ...现在,当锁变为无主时,仍然使用 FIFO 唤醒算法,但锁会立即标记为不可用。 另一个线程可以在唤醒线程被调度之前潜入并获取锁

其他线程可以是刚刚释放锁的线程。在您的代码中,释放互斥锁的线程接下来要做的就是尝试重新获取互斥锁,这很适合这样做。

【讨论】:

  • 即使使用公平锁,预想的结果也不能保证,甚至不太可能。一个人需要在两个方向上进行明确的同步才能来回获得完美的乒乓球。如果一个人正在编写类似管道的东西,通常会提供一定程度的缓冲,但您仍然需要多个互斥体来完成等待。
  • 使用附加到两个进程的调试器可以通过强制执行“乒乓”序列来证实这一假设
  • @ZalmanStern 是完全正确的。即使锁是完全公平的,代码也会被破坏。没有什么可以保证下一个应该运行的线程在互斥锁被另一个线程释放之前实际上已经到达它在互斥锁上等待的点。
猜你喜欢
  • 2011-06-10
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
相关资源
最近更新 更多