使用互斥锁

时间:2017-11-15 12:17:28

标签: c++ winapi

我有两个流程:

  1. 第一个创建memory mapped regionmutex并生成 第二个过程。然后在memory mapped region
  2. 中写下一些数字
  3. 第二个打开memory mapped regionopens the mutex,然后读取process 1写的数字。
  4. 我打算第一个进程写一对数字,第二个进程立即读取它。

    process 2似乎正在挨饿。

    我做错了什么?

    流程1:

    #include "stdafx.h"
    #include <windows.h>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        DWORD memSize = 400 * sizeof(DWORD);
        HANDLE map_file = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, memSize, TEXT("mem1"));
    
        if (map_file == NULL)
        {
            _tprintf(_T("(Parent) File mapping is null\n"));
            return 1;
        }
    
        char* map_ptr = (char *) MapViewOfFile(map_file, FILE_MAP_READ, 0, 0, 0);
        if (map_ptr == NULL)
        {
            _tprintf(_T("(Parent) PTR is null \n"));
        }
    
        HANDLE hMutex = CreateMutex(NULL, TRUE, _T("mt"));
        LPTSTR szCmdline = _tcsdup(TEXT("C:\\Users\\cristi\\source\\repos\\process_synchronization_reader\\Debug\\process_synchronization_reader.exe"));
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));
    
        if (!CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
        {
            _tprintf(_T("Process created\n"));
        }
    
        _tprintf(_T("pare ca s-a creat"));
        for (int i = 1; i <= 200; ++i)
        {
            WaitForSingleObject(hMutex, INFINITE);
    
            _tprintf(_T("(Parent %d) writing from the parent\n"), i);
            DWORD a, b;
    
            CopyMemory((LPVOID) &a, map_ptr, sizeof(DWORD));
            map_ptr += sizeof (DWORD);
    
            CopyMemory((LPVOID) &b, map_ptr, sizeof(DWORD));
            map_ptr += sizeof(DWORD);
    
            ReleaseMutex(hMutex);
        }
    
        int n;
        cin >> n;
        CloseHandle(map_file);
    
        return 0;
    }
    

    流程2:

    #include "stdafx.h"
    #include <windows.h>
    
    int main()
    {
        HANDLE map_file = OpenFileMapping(FILE_MAP_READ, FALSE, TEXT("mem1"));
    
        if (map_file == NULL)
        {
            _tprintf(_T("(Child) File mapping is null\n"));
            return 1;
        }
    
        char* map_ptr = (char *) MapViewOfFile(map_file, FILE_MAP_READ, 0, 0, 0);
    
        if (map_ptr == NULL)
        {
            _tprintf(_T("(Child) PTR is null \n"));
        }
    
        _tprintf(_T("(CHILD) BEfore reading the first number\n"));
        HANDLE hMutex = OpenMutex(SYNCHRONIZE, TRUE, _T("mt"));
        for (int i = 1; i <= 200; i++)
        {       
            WaitForSingleObject(hMutex, INFINITE);
            DWORD a = i;
            DWORD b = 2 * i;
    
            CopyMemory((LPVOID) map_ptr, &a, sizeof(DWORD));
            map_ptr += sizeof(DWORD);
    
            CopyMemory((LPVOID) map_ptr, &b, sizeof(DWORD));
            map_ptr += sizeof(DWORD);
    
            _tprintf(_T("[================================================]\n"));
            _tprintf(_T("( %d %d )\n"), a, b);
            _tprintf(_T("[=================================================]\n"));
    
            ReleaseMutex(hMutex);
        }
    
        return 0;
    }
    

2 个答案:

答案 0 :(得分:1)

对于从共享内存获得顺序写入/读取,我们需要2个事件(让它命名为)。

第一个帖子:

  1. 写数据
  2. 信号事件
  3. 等待事件或中断循环
  4. 转到1
  5. 第二个帖子:

    1. 等待事件
    2. 读取数据
    3. 中断循环或信号事件
    4. 转到1
    5. 与此解决方案不同,互斥锁无法提供读/写序列。互斥保证直到一个线程将访问共享数据(读或写),另一个线程将不会在并发中执行此操作。但这不能连续多次阻止写入或读取。真的 - 在进程2开始时插入消息框 - 在他第一次尝试获取互斥锁之前 - 第一个进程已经很多次获取并释放互斥锁。或者如果一个线程将在释放和等待互斥之间暂停 - 同时另一个线程多次等待并释放它。所以代码看起来像:

      struct SHARED_DATA
      {
          ULONG id;
          ULONG nLoops;
          BOOL bTask;
      };
      
      DWORD proc2(SHARED_DATA* p)
      {   
          if (HANDLE hLowEvent = OpenEvent(SYNCHRONIZE, FALSE, L"LowEvent"))
          {
              if (HANDLE hHighEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, L"hHighEvent"))
              {
                  ULONG id = GetCurrentThreadId();
      
                  for(;;) 
                  {
                      if (WaitForSingleObject(hLowEvent, INFINITE) != WAIT_OBJECT_0)
                      {
                          break;
                      }
      
                      // ++ checking for sequence
                      if (p->id == id)
                      {
                          __debugbreak();// must never be
                      }
      
                      p->id = id;
                      // -- checking for sequence
      
                      if (!p->bTask)
                      {
                          // no more task
                          break;
                      }
      
                      // task done
                      p->bTask = FALSE;
      
                      // signal to #1
                      if (!SetEvent(hHighEvent))
                      {
                          break;
                      }
                  }
      
                  CloseHandle(hHighEvent);
              }
              CloseHandle(hLowEvent);
          }
      
          return 0;
      }
      
      DWORD proc1(SHARED_DATA* p)
      {
          if (HANDLE hLowEvent = CreateEvent(0, FALSE, FALSE, L"LowEvent"))
          {
              if (HANDLE hHighEvent = CreateEvent(0, FALSE, FALSE, L"hHighEvent"))
              {
                  ULONG id = GetCurrentThreadId();
      
                  p->nLoops = 0x1000;
                  p->id = 0;
                  p->bTask = FALSE;
      
                  // exec proc2 here
                  goto __1;
      
                  do 
                  {
                      if (WaitForSingleObject(hHighEvent, INFINITE) != WAIT_OBJECT_0)
                      {
                          break;
                      }
      
                      if (p->bTask)
                      {
                          __debugbreak();
                      }
      
                      // ++ checking for sequence
                      if (p->id == id)
                      {
                          __debugbreak();// must never be
                      }
      __1:
                      p->id = id;
                      // -- checking for sequence
      
                      p->bTask = 0 < --p->nLoops;
      
                      // signal to #2
                      if (!SetEvent(hLowEvent))
                      {
                          break;
                      }
      
                  } while (p->nLoops);
      
                  CloseHandle(hHighEvent);
              }
              CloseHandle(hLowEvent);
          }
      
          return 0;
      }
      

答案 1 :(得分:0)

您创建一个最初拥有的互斥锁(CreateMutex的第二个参数是TRUE),然后在其上调用等待函数。因此,即使在调用ReleaseMutex之后,它仍然由第一个进程的主线程拥有。

将参数更改为FALSE,或者跳过为{em>第一次循环迭代调用WaitForSingleObject