用信号量解決專欄提出的那個線程同步的問題有點大材小用了,不過依然可以完善的解決。基本思想就是設定一個最大資源數為1的信号量,初始時資源為0,主線程CreadThread後調用WaitSingleObject來等待信号量觸發,子線程啟動後操作完成需要工作後調用ReleaseSemaphore函數,将資源數增加到1信号量被觸發。當WaitSingleObject調用後,資源會減1,資源數重新變成0。
代碼如下:
運作結果如下圖:
2、在經典多線程問題中設定一個信号量和一個關鍵段。用信号量處理主線程與子線程的同步,用關鍵段來處理各子線程間的互斥。詳見代碼:
[html] view plain copy
- #include <stdio.h>
- #include <process.h>
- #include <windows.h>
- long g_nNum;
- unsigned int __stdcall Fun(void *pPM);
- const int THREAD_NUM = 10;
- //信号量與關鍵段
- HANDLE g_hThreadParameter;
- CRITICAL_SECTION g_csThreadCode;
- int main()
- {
- printf(" 經典線程同步 信号量Semaphore\n");
- printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
- //初始化信号量和關鍵段
- g_hThreadParameter = CreateSemaphore(NULL, 0, 1, NULL);//目前0個資源,最大允許1個同時通路
- InitializeCriticalSection(&g_csThreadCode);
- HANDLE handle[THREAD_NUM];
- g_nNum = 0;
- int i = 0;
- while (i < THREAD_NUM)
- {
- handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
- WaitForSingleObject(g_hThreadParameter, INFINITE);//等待信号量>0
- ++i;
- }
- WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
- //銷毀信号量和關鍵段
- DeleteCriticalSection(&g_csThreadCode);
- CloseHandle(g_hThreadParameter);
- for (i = 0; i < THREAD_NUM; i++)
- CloseHandle(handle[i]);
- return 0;
- }
- unsigned int __stdcall Fun(void *pPM)
- {
- int nThreadNum = *(int *)pPM;
- ReleaseSemaphore(g_hThreadParameter, 1, NULL);//信号量++
- Sleep(50);//some work should to do
- EnterCriticalSection(&g_csThreadCode);
- ++g_nNum;
- Sleep(0);//some work should to do
- printf("線程編号為%d 全局資源值為%d\n", nThreadNum, g_nNum);
- LeaveCriticalSection(&g_csThreadCode);
- return 0;
- }
運作結果:
可以看出來,信号量也可以解決線程之間的同步問題。
由于信号量可以計算資源目前剩餘量并根據目前剩餘量與零比較來決定信号量是處于觸發狀态或是未觸發狀态,是以信号量的應用範圍相當廣泛。本系列的《多線程八 生産者消費者經典問題》将再次使用它來解決線程同步問題,歡迎大家參閱。
至此,經典線程同步問題全部結束了,下一篇《多線程七 經典線程同步與互斥總結》将會對其作個總結以梳理各知識點。