2017-11-10 189 views
0

我有2个进程。第一个将一些数据发送给另一个,同步每一步。 实际发送的数据如下:Mutex不同步C++

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); 
+1

不要在您尝试同步的代码内部创建互斥锁。 –

+5

你的互斥体的心智模型似乎是错误的。在这里没有任何问题可以回答,除了告诉你一个互斥体不会做你认为它所做的事。 –

+5

一个互斥体只是说一次只能有一件事。它没有说明各个参与者获得它的顺序。你所描述的是一个完全有效的结果。您可能需要一些排序。 – GManNickG

回答

1

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

具体互斥达菲说以下(由我添加高亮):

当然,视窗锁仍然是一个却有点公平的。互斥锁的等待列表按FIFO顺序保存,操作系统始终将线程唤醒到等待队列的前端。 ...现在,当锁被取消时,仍然使用FIFO唤醒算法,但锁立即被标记为不可用。 另一个线程可以潜入并采取锁之前的唤醒线程甚至计划

,其他线程可以是刚刚发布的锁的线程。在你的代码中,释放互斥锁的线程所做的下一件事就是重新获取互斥锁,这是一个很好的位置。

+2

即使使用公平的锁,预期的结果也不能保证或甚至是特别可能的。人们需要在两个方向上进行明确的同步才能获得完美的乒乓球来回。一般来说,如果你正在写一个类似管道的东西,但是你仍然需要超过一个互斥量来完成等待,那么通常会提供一定程度的缓冲。 –

+0

使用连接到两个进程的调试器可以通过强制执行“乒乓”序列来确认此假设 –

+0

在两个WaitForSingleObject上设置断点 –