(1)互斥對象:函數CreateMutex。在多核下工作不正常。
(2)事件對象:函數CreateEvent、SetEvent、ResetEvent、WaitForSingleObject,應當使用自動重設的事件對象。在多核下工作正常。
(3)關鍵程式碼片段:類CRITICAL_SECTION,函數InitializeCriticalSection、DeleteCriticalSection、EnterCriticalSection、LeaveCriticalSection。在多核下工作基本正常,但是會出現:“"xxx"指令引用的"xxx"記憶體。該記憶體不能為"written"。”。需要注意線程死結問題。
三者比較:
互斥對象和事件對象都屬於核心對象,速度較慢。但可以在多個進程中的各個線程間進行同步。
關鍵程式碼片段工作在使用者方式下,同步速度較快,但容易進入死結狀態,因為在等待進入關鍵程式碼片段時無法設定逾時值。通常,首選關鍵程式碼片段。
其使用也比較簡單,如果在MFC中的話,可在建構函式調用InitializeCriticalSection,在建構函式調用DeleteCriticalSection,在所需保護的代碼前調用EnterCriticalSection,在訪問完所需保護的資源後調用LeaveCriticalSection即可。
----------------例子:互斥對象------------------------------------------------
#include <windows.h><br />#include <iostream.h><br />int index=0;<br />int tickets=20;<br />HANDLE hMutex;<br />DWORD WINAPI Fun1Proc(LPVOID lpPrama)<br />{<br />while(TRUE)<br />{<br />WaitForSingleObject(hMutex,INFINITE);<br />if (tickets>0)<br />{<br />Sleep(1);<br /> cout<<"thread 1 sell ticket: "<<tickets--<<endl;<br />}<br />else<br />{<br />break;<br />}<br />ReleaseMutex(hMutex);<br />}<br />return 0;<br />}<br />DWORD WINAPI Fun2Proc(LPVOID lpPrama)<br />{<br />while(TRUE)<br />{<br />WaitForSingleObject(hMutex,INFINITE);<br />if (tickets>0)<br />{<br />Sleep(1);<br />cout<<"thread 2 sell ticket: "<<tickets--<<endl;<br />}<br />else<br />{<br />break;<br />}<br />ReleaseMutex(hMutex);<br />}</p><p>return 0;<br />}<br />void main()<br />{<br />HANDLE hThread1;<br />HANDLE hThread2;<br />hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);<br />hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);<br />CloseHandle(hThread1);<br />CloseHandle(hThread2);<br />hMutex=CreateMutex(NULL,FALSE,NULL);<br />Sleep(1000);<br />}
正確的結果是由20遞減到1,但是本程式會出現以下錯誤結果:
thread 1 sell ticket: 20
thread 1 sell ticket: 20
thread 2 sell ticket: 19
thread 1 sell ticket: 18
...
thread 2 sell ticket: 1
----------------------------------------------------------------------------------
----------------例子:事件對象------------------------------------------------
#include <windows.h><br />#include <iostream.h><br />int tickets=20;<br />HANDLE g_hEvent;<br />DWORD WINAPI Fun1Proc(LPVOID lpPrama)<br />{<br />while(TRUE)<br />{<br />WaitForSingleObject(g_hEvent,INFINITE);<br />//ResetEvent(g_hEvent);<br />if (tickets>0)<br />{<br />Sleep(1);<br /> cout<<"thread 1 sell ticket: "<<tickets--<<endl;<br />SetEvent(g_hEvent);<br />}<br />else<br />{<br />SetEvent(g_hEvent);<br />break;<br />}<br />}<br />return 0;<br />}<br />DWORD WINAPI Fun2Proc(LPVOID lpPrama)<br />{<br />while(TRUE)<br />{<br />WaitForSingleObject(g_hEvent,INFINITE);<br />//ResetEvent(g_hEvent);<br />if (tickets>0)<br />{<br />Sleep(1);<br /> cout<<"thread 2 sell ticket: "<<tickets--<<endl;<br />SetEvent(g_hEvent);<br />}<br />else<br />{<br />SetEvent(g_hEvent);<br />break;<br />}<br />}<br />return 0;<br />}<br />void main()<br />{<br />HANDLE hThread1;<br />HANDLE hThread2;<br />g_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);<br />SetEvent(g_hEvent);<br />hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);<br />hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);<br />CloseHandle(hThread1);<br />CloseHandle(hThread2);<br />Sleep(1000);<br />CloseHandle(g_hEvent);<br />}
----------------例子:關鍵程式碼片段---------------------------------------------
//<QA>注釋掉兩個Mark的程式碼後,出現記憶體不能寫異常。<br />#include <windows.h><br />#include <iostream.h><br />int tickets=20;<br />CRITICAL_SECTION g_cs;<br />DWORD WINAPI Fun1Proc(LPVOID lpPrama)<br />{<br />while(TRUE)<br />{<br />EnterCriticalSection(&g_cs);<br />Sleep(1); //Mark<br />if (tickets>0)<br />{<br />Sleep(1);<br /> cout<<"thread 1 sell ticket: "<<tickets--<<endl;<br />LeaveCriticalSection(&g_cs);<br />}<br />else<br />{<br />LeaveCriticalSection(&g_cs);<br />break;<br />}<br />}<br />return 0;<br />}<br />DWORD WINAPI Fun2Proc(LPVOID lpPrama)<br />{<br />while(TRUE)<br />{<br />EnterCriticalSection(&g_cs);<br />Sleep(1); //Mark<br />if (tickets>0)<br />{<br />Sleep(1);<br /> cout<<"thread 2 sell ticket: "<<tickets--<<endl;<br />LeaveCriticalSection(&g_cs);<br />}<br />else<br />{<br />LeaveCriticalSection(&g_cs);<br />break;<br />}<br />}<br />return 0;<br />}<br />void main()<br />{<br />HANDLE hThread1;<br />HANDLE hThread2;<br />hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);<br />hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);<br />CloseHandle(hThread1);<br />CloseHandle(hThread2);<br />InitializeCriticalSection(&g_cs);<br />Sleep(1000);<br />DeleteCriticalSection(&g_cs);<br />}