c++多线程同步(1)

此篇讨论一下c++中的线程同步。

线程同步方式:

    临界区

    事件

    互斥量

   信号量

为什么要线程同步?

       从之前的讨论及实际的项目中,可以看到线程同步给我们带来了很多便利性,但是多线程也同时给我们带来了很多麻烦:一方面,在开发调试阶段带来了很大的难度;另一方面,则需要考虑资源访问的一致性原则。因为在程序中使用多线程的时候,每一个线程并不会各行各事,每个线程之间必然会存在一些联系。如果两个或者多个线程访问同一个独占性的系统资源,这样会导致系统错误。

下面对实现线程同步的几种方法分别介绍

(1) 临界区

临界区是一段独占对某些共享资源的访问代码,在任意时刻只允许一个线程对共享资源访问。如果有多个线程试图同时访问临界区,那么只有一个线程进入临界区,其他试图访问临界区的线程将被挂起,并一直持续到进入临界区的线程离开,其他线程可以继续抢占临界区。

       需要说明的是,在使用临界区时,一般不允许其运行时间过长,因为只要进入临界区的线程不离开,其他视图进入此临界区的线程都会挂起,进入等待状态,因此这样在一定程度上影响程序的性能。因此,不要使临界区一直处于未释放的状态。

     还需要注意的是,虽然临界区同步速度比较快,但是只能用来同步本进程内的线程,而不能跨线程同步

     MFC中,有一个CCriticalSection类,此类中有两个方法Lock和UnLock,只需要在需要同步的代码前后假如这两个函数,就可以实现临界区资源。

     例子如下(部分代码):

   

[cpp]  view plain copy
  1. CCriticalSection critical_section;  
  2. char g_array[10];  
  3.   
  4. UINT WriteW(LPVOID pParam)  
  5. {  
  6.     CEdit *pEdit = (CEdit *)pParam;  
  7.     pEdit->SetWindowText(" ");  
  8.     <span style="color:#ff0000;">critical_section.Lock()</span>;//锁定临界区  
  9.   
  10.     for (int i=0; i<10; i++)  
  11.     {  
  12.         g_array[i]='W';  
  13.         pEdit->SetWindowText(g_array);  
  14.         Sleep(1000);  
  15.     }  
  16.     <span style="color:#ff0000;">critical_section.Unlock();</span>  
  17.     return 0;  
  18. }  
  19. UINT WriteD(LPVOID pParam)  
  20. {  
  21.     CEdit *pEdit = (CEdit *)pParam;  
  22.     pEdit->SetWindowText(" ");  
  23.     <span style="color:#ff0000;">critical_section.Lock();</span>  
  24.       
  25.     for (int i=0; i<10; i++)  
  26.     {  
  27.         g_array[i]='D';  
  28.         pEdit->SetWindowText(g_array);  
  29.         Sleep(1000);  
  30.     }  
  31.     <span style="color:#ff0000;">critical_section.Unlock();</span>  
  32.     return 0;  
  33.   
  34. }  

创建线程:

[cpp]  view plain copy
  1. void CMthread8Dlg::OnWritew()   
  2. {  
  3.     // TODO: Add your control notification handler code here  
  4.     CWinThread *pWriteW = AfxBeginThread((AFX_THREADPROC)WriteW,  
  5.                                         &m_ctrW,  
  6.                                         THREAD_PRIORITY_NORMAL,  
  7.                                         0,  
  8.                                         CREATE_SUSPENDED);  
  9.     pWriteW->ResumeThread();  
  10. }  
  11.   
  12. void CMthread8Dlg::OnWrited()   
  13. {  
  14.     // TODO: Add your control notification handler code here  
  15.     CWinThread *pWriteD = AfxBeginThread((AFX_THREADPROC)WriteD,  
  16.                                         &m_ctrD,  
  17.                                         THREAD_PRIORITY_NORMAL,  
  18.                                         0,  
  19.                                         CREATE_SUSPENDED);  
  20.     pWriteD->ResumeThread();  
  21. }  
执行结果:

c++多线程同步(1)_第1张图片

从执行结果看,读的线程只能等到写的线程从临界区出来后才能访问临界区。


(2) 事件

  实例参见本博客:c++CreateEvent函数在多线程中使用及实例
  此实例中采用CreateEvent 事件函数实现多线程同步的。

  也可以采用MFC中的CEvent类实现多线程同步。   

部分代码如下:

[cpp]  view plain copy
  1. CEvent event;  
  2. char g_array[10];  
  3.   
  4. UINT WriteW(LPVOID pParam)  
  5. {  
  6.     CEdit *pEdit = (CEdit *)pParam;  
  7.     pEdit->SetWindowText(" ");  
  8.   
  9.     for (int i=0; i<10; i++)  
  10.     {  
  11.         g_array[i] = 'W';  
  12.         pEdit->SetWindowText(g_array);  
  13.         Sleep(200);  
  14.     }  
  15.     event.SetEvent();  
  16.     return 0;  
  17. }     
  18. UINT WriteD(LPVOID pParam)  
  19. {  
  20.     CEdit *pEdit = (CEdit *)pParam;  
  21.     pEdit->SetWindowText(" ");  
  22.     <span style="color:#ff0000;">WaitForSingleObject(event,INFINITE);</span>  
  23.     for (int i=0; i<10; i++)  
  24.     {  
  25.         g_array[i] = 'W';  
  26.         pEdit->SetWindowText(g_array);  
  27.         Sleep(200);  
  28.     }  
  29.     return 0;  
  30. }  
创建线程的代码和临界区中显示的代码一样。

主要通过WaitForSingleObject函数实现多线程的同步。此函数等待上一个线程释放事件,即事件变成有信号状态时,才执行此线程下面的程序。

你可能感兴趣的:(c++多线程同步(1))