秒殺多線程第四篇 一個經典的多線程同步問題

 

原文連接:http://blog.csdn.net/morewindows/article/details/7442333windows

上一篇《秒殺多線程第三篇原子操做 Interlocked系列函數》中介紹了原子操做在多進程中的做用,如今來個複雜點的。這個問題涉及到線程的同步和互斥,是一道很是有表明性的多線程同步問題,若是能將這個問題搞清楚,那麼對多線程同步也就打下了良好的基礎。多線程

 

程序描述:框架

主線程啓動10個子線程並將表示子線程序號的變量地址做爲參數傳遞給子線程。子線程接收參數 -> sleep(50) -> 全局變量++ -> sleep(0) -> 輸出參數和全局變量。函數

要求:spa

1.子線程輸出的線程序號不能重複。.net

2.全局變量的輸出必須遞增。線程

下面畫了個簡單的示意圖:指針

分析下這個問題的考察點,主要考察點有二個:blog

1.主線程建立子線程並傳入一個指向變量地址的指針做參數,因爲線程啓動需要花費必定的時間,因此在子線程根據這個指針訪問並保存數據前,主線程應等待子線程保存完畢後才能改動該參數並啓動下一個線程。這涉及到主線程與子線程之間的同步進程

2.子線程之間會互斥的改動和輸出全局變量。要求全局變量的輸出必須遞增。這涉及到各子線程間的互斥

 

下面列出這個程序的基本框架,能夠在此代碼基礎上進行修改和驗證。

[cpp] view plaincopy
 
  1. //經典線程同步互斥問題  
  2. #include <stdio.h>  
  3. #include <process.h>  
  4. #include <windows.h>  
  5.   
  6. long g_nNum; //全局資源  
  7. unsigned int __stdcall Fun(void *pPM); //線程函數  
  8. const int THREAD_NUM = 10; //子線程個數  
  9.   
  10. int main()  
  11. {  
  12.     g_nNum = 0;  
  13.     HANDLE  handle[THREAD_NUM];  
  14.       
  15.     int i = 0;  
  16.     while (i < THREAD_NUM)   
  17.     {  
  18.         handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);  
  19.         i++;//等子線程接收到參數時主線程可能改變了這個i的值  
  20.     }  
  21.     //保證子線程已所有運行結束  
  22.     WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);    
  23.     return 0;  
  24. }  
  25.   
  26. unsigned int __stdcall Fun(void *pPM)  
  27. {  
  28. //因爲建立線程是要必定的開銷的,因此新線程並不能第一時間執行到這來  
  29.     int nThreadNum = *(int *)pPM; //子線程獲取參數  
  30.     Sleep(50);//some work should to do  
  31.     g_nNum++;  //處理全局資源  
  32.     Sleep(0);//some work should to do  
  33.     printf("線程編號爲%d  全局資源值爲%d\n", nThreadNum, g_nNum);  
  34.     return 0;  
  35. }  

運行結果能夠參考下列圖示,強烈建議讀者親自試一試。

圖1

圖2

圖3

能夠看出,運行結果徹底是混亂和不可預知的。本系列將會運用Windows平臺下各類手段包括關鍵段,事件,互斥量,信號量等等來解決這個問題並做一份全面的總結,敬請關注。

 

秒殺多線程第五篇 經典線程同步 關鍵段CS》已經發布,歡迎參閱。

秒殺多線程第六篇 經典線程同步 事件Event》已經發布,歡迎參閱。

秒殺多線程第七篇 經典線程同步 互斥量Mutex已經發布,歡迎參閱。

秒殺多線程第八篇 經典線程同步 信號量Semaphore已經發布,歡迎參閱。 

相關文章
相關標籤/搜索