多线程编程实例----线程同步之互斥量

来源:互联网 发布:淘宝信誉有什么用 编辑:程序博客网 时间:2024/05/19 13:28

互斥量和临界区差不多的,但是比临界区好理解,而且互斥量可以用于进程间的同步,所以我个人还是觉得相比于临界区而言,互斥量更加易用些。

    其实这个演示程序的代码和前面使用临界区的代码差不多了,还是来简单的看一下吧:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  // TODO: Place code here.
 MSG msg;
 HACCEL hAccelTable;

 // Initialize global strings
 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
 LoadString(hInstance, IDC_MUTEX, szWindowClass, MAX_LOADSTRING);
 MyRegisterClass(hInstance);

 // Perform application initialization:
 if (!InitInstance (hInstance, nCmdShow))
 {
  return FALSE;
 }

 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MUTEX);
 // Main message loop:
 while (GetMessage(&msg, NULL, 0, 0))
 {
  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }

 return msg.wParam;
}

    这是主函数,这个主函数没有一行代码是需要我们自己编写的,这是在生成Win32程序时,系统帮我们加上的,其实没有必要摆出来,不说废话来,来看看,窗口过程函数:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 int wmId, wmEvent;
 PAINTSTRUCT ps;
 HDC hdc;
 TCHAR szHello[MAX_LOADSTRING];
 LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);


 switch (message)
 {
 case WM_CREATE:
  m_gMutex = CreateMutex(NULL,FALSE,NULL);
  hThreads[0] = CreateThread(NULL,0,WriteProc,NULL,0,NULL); 
  hThreads[1] = CreateThread(NULL,0,ReadProc,hWnd,0,NULL);
  
 case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);
  // Parse the menu selections:
  switch (wmId)
  {
  case IDM_ABOUT:
   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
   break;
  case IDM_EXIT:
   DestroyWindow(hWnd);
   break;
  default:
   return DefWindowProc(hWnd, message, wParam, lParam);
  }
  break;
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);
  // TODO: Add any drawing code here...
  RECT rt;
  GetClientRect(hWnd, &rt);
  DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
  EndPaint(hWnd, &ps);
  break;
 case WM_DESTROY:
  WaitForMultipleObjects(2,hThreads,TRUE,INFINITE);
  CloseHandle(m_gMutex);   
  CloseHandle(hThreads[0]);
  CloseHandle(hThreads[1]);
  PostQuitMessage(0);
  break;
 default:
  return DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}

    这个窗口过程函数响应了很多的消息,最重要的就是WM_CREATE,相应这个消息的时候,创建了一个互斥变量,并且启动了两个线程,一个是读线程,另一个是写线程。

    下面来看看这两个线程入口函数:

DWORD WINAPI WriteProc(LPVOID pParm)
{
 DWORD dw;
 for (int j=0;j<10;j++)
 {
  dw = WaitForSingleObject(m_gMutex,INFINITE);
  if (dw == WAIT_OBJECT_0) {
   for (int i=0;i<10;i++)
    iArray[i]=j;
   ReleaseMutex(m_gMutex);
   Sleep(1);
  }
  
  else{
   break;
  }
  
 }
 return 0;
}

DWORD WINAPI ReadProc(LPVOID pParm)
{
 int aArray[10];

 DWORD dw;
 for (int i=0;i<10;i++)
 {
  //wait for the mutex to become signaled
  dw = WaitForSingleObject(m_gMutex,INFINITE);
  if (dw == WAIT_OBJECT_0) {
   //mutex became unsignaled
   for (int k=0;k<10;k++)
   {
    aArray[k]=iArray[k];
   }
  
  
   char str[255];
   str[0]=0;
   for (int j=0;j<10;j++)
   {
    int len=strlen(str);
    wsprintf(&str[len],"%d",aArray[j]);
   }
   ::MessageBox(NULL,str,"Thread Read Proc",MB_OK);// (HWND)param
   ReleaseMutex(m_gMutex);
   //mutex became signaled 
  }
  else{
   //the mutex is abandoned
   break;
  }  
 }
 return 0;
}
    从这两个函数可以看出,当写线程要往全局变量里面写数据的时候,首先需要 WaitForSingleObject(m_gMutex,INFINITE);这是干什么呢?这是在等待,等待m_gMutex变为有信号的状态,怎么理解这个有信号的状态呢?其实很简单,有信号就是我可以使用啊,等待的时刻就是我可以使用了,dw == WAIT_OBJECT_0怎么理解呢?因为WaitForSingleObject可能有其他的返回值,当返回值是这个的时候,才能说明我们等待的变量变为有信号了,这样的话,我们就可以开始使用cpu了,运行自己的程序吧,但是有一点不要忘记,使用完互斥变量之后,要记住ReleaseMutex,这样其他等待的线程才能开始使用cpu了,很简单的东西,却可以用来同步线程,其实同步线程并是不是想的那么麻烦。

原创粉丝点击