用于线程互斥的方法有:原子锁,关键区域(CriticalSection),互斥量(Mutex),。
用于线程同步的方法有:事件(Event),信号量(Semaphore),定时器(这里我们不谈)。
InterlockedIncrement(LONG volatile*Addend);
InterlockedDecrement(LONG volatile*Addend);
InterlockedExchangeAdd(LONG volatile*Addend, LONGValue);
InterlockedExchange(LONG volatile*Target, LONGValue);
例子:
没有使用原子锁的情况:
#include <stdio.h> #include <windows.h> #include <process.h> volatile long g_nLoginCount; unsigned int __stdcall Fun(void *pPM); const DWORD THREAD_NUM = 50; unsigned int __stdcall ThreadFun(void *pPM) { g_nLoginCount++; return 0; } int main() { int num= 20; while (num--) { g_nLoginCount = 0; int i; HANDLE handle[THREAD_NUM]; for (i = 0; i < THREAD_NUM; i++) handle[i] = (HANDLE )_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL); WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); for(i=0;i<THREAD_NUM;i++) { CloseHandle(handle[i]); } printf("%d个线程执行i++,结果是%d\n", THREAD_NUM, g_nLoginCount); } return 0; }这里解释下为什么搞几个线程,还弄的这么复杂,一个while循环,一个for循环,这是因为不能一次创建很多线程,否则会出问题,你自己可以试试依次性创建100个线程试试,会出问题的。貌似一次最多只能创建64个线程。所以这里采用了这么复杂的方法。
使用原子锁的情况:
unsigned int __stdcall ThreadFun(void *pPM) { g_nLoginCount++; InterlockedIncrement(&g_nLoginCount); return 0; }
void InitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection); -----------初始化关键区域
void DeleteCriticalSection(LPCRITICAL_SECTIONlpCriticalSection); -----------删除关键区域
void EnterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection); -----------进入关键区域#include <stdio.h> #include <process.h> #include <windows.h> long g_nNum; unsigned int __stdcall Fun(void *pPM); const int THREAD_NUM = 10; int main() { HANDLE handle[THREAD_NUM]; g_nNum = 0; int i = 0; while (i < THREAD_NUM) { handle[i++] = (HANDLE)_beginthreadex(NULL, 0, Fun, NULL, 0, NULL); } WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); for(i=0;i<sizeof(handle);i++) { CloseHandle(handle[i]); } return 0; } unsigned int __stdcall Fun(void *pPM) { Sleep(50); g_nNum++; Sleep(0); printf("当前计数为:%d\n",g_nNum); return 0; }
CRITICAL_SECTION g_csThreadCode;
InitializeCriticalSection(&g_csThreadCode);
DeleteCriticalSection(&g_csThreadCode);
unsigned int __stdcall Fun(void *pPM) { Sleep(50); EnterCriticalSection(&g_csThreadCode); g_nNum++; Sleep(0); printf("当前计数为:%d\n",g_nNum); LeaveCriticalSection(&g_csThreadCode); return 0; }
HANDLECreateEvent(
LPSECURITY_ATTRIBUTESlpEventAttributes,
BOOLbManualReset,
BOOLbInitialState,
LPCTSTRlpName
);---------创建事件。
HANDLEOpenEvent(
DWORDdwDesiredAccess,
BOOLbInheritHandle,
LPCTSTRlpName
);------------打开事件
BOOLSetEvent(HANDLEhEvent);----------触发事件
BOOLResetEvent(HANDLEhEvent);-----------将事件设为未触发
#include <stdio.h> #include <process.h> #include <windows.h> long g_nNum; unsigned int __stdcall Fun(void *pPM); const int THREAD_NUM = 10; CRITICAL_SECTION g_csThreadCode; int main() { 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); } WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); for(i=0;i<sizeof(handle);i++) { CloseHandle(handle[i]); } DeleteCriticalSection(&g_csThreadCode); return 0; } unsigned int __stdcall Fun(void *pPM) { int nThreadNum = *(int *)pPM; Sleep(50); EnterCriticalSection(&g_csThreadCode); g_nNum++; Sleep(0); printf("当前线程为:%d,当前计数为:%d\n",nThreadNum,g_nNum); LeaveCriticalSection(&g_csThreadCode); return 0; }
#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_hThreadEvent; CRITICAL_SECTION g_csThreadCode; int main() { g_hThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 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_hThreadEvent, INFINITE); ResetEvent(g_hThreadEvent); i++; } WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); for(i=0;i<sizeof(handle);i++) { CloseHandle(handle[i]); } CloseHandle(g_hThreadEvent); DeleteCriticalSection(&g_csThreadCode); return 0; } unsigned int __stdcall Fun(void *pPM) { int nThreadNum = *(int *)pPM; SetEvent(g_hThreadEvent); Sleep(50); EnterCriticalSection(&g_csThreadCode); g_nNum++; Sleep(0); printf("当前线程为:%d,当前计数为:%d\n",nThreadNum,g_nNum); LeaveCriticalSection(&g_csThreadCode); return 0; }线程ID符合要求。。
#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_mutex; int main() { g_mutex = CreateMutex(NULL, FALSE, NULL); HANDLE handle[THREAD_NUM]; g_nNum = 0; int i = 0; while (i < THREAD_NUM) { handle[i++] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL); } WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); CloseHandle(g_mutex); for (i = 0; i < THREAD_NUM; i++) CloseHandle(handle[i]); return 0; } unsigned int __stdcall Fun(void *pPM) { Sleep(50); WaitForSingleObject(g_mutex,INFINITE); g_nNum++; Sleep(0); printf("当前计数为:%d\n",g_nNum); ReleaseMutex(g_mutex); return 0; }
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);------------------创建信号量
HANDLE OpenSemaphore(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);------------------打开信号量
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);--------------------释放信号量
注意:信号量的值不可能小于0。
#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_Semaphore; CRITICAL_SECTION g_CriticalSection; int main() { g_Semaphore = CreateSemaphore(NULL, 0, 1, NULL); InitializeCriticalSection(&g_CriticalSection); 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_Semaphore, INFINITE); ++i; } WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); DeleteCriticalSection(&g_CriticalSection); CloseHandle(g_Semaphore); for (i = 0; i < THREAD_NUM; i++) CloseHandle(handle[i]); return 0; } unsigned int __stdcall Fun(void *pPM) { int nThreadNum = *(int *)pPM; ReleaseSemaphore(g_Semaphore, 1, NULL); Sleep(50); EnterCriticalSection(&g_CriticalSection); ++g_nNum; Sleep(0); printf("当前线程为:%d,当前计数为:%d\n",nThreadNum,g_nNum); LeaveCriticalSection(&g_CriticalSection); return 0; }