// ssss.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include<stdio.h> CRITICAL_SECTION cs1; CRITICAL_SECTION cs2; int y; DWORD WINAPI Proc1(LPVOID lpParameter) { for(int i = 0; i < 1000; i++) { Sleep(1000); EnterCriticalSection(&cs1); EnterCriticalSection(&cs2); printf("1++++++++++:%d ", ++y); LeaveCriticalSection(&cs2); LeaveCriticalSection(&cs1); } return 0; } DWORD WINAPI Proc2(LPVOID lpParameter) { for(int i = 0; i < 1000; i++) { Sleep(1000); EnterCriticalSection(&cs2); EnterCriticalSection(&cs1); printf("2----------:%d ", ++y); LeaveCriticalSection(&cs1); LeaveCriticalSection(&cs2); } return 0; } int main(int argc, char* argv[]) { HANDLE h1 = ::CreateThread(NULL, 0, Proc1, NULL, 0, NULL); ::CloseHandle(h1); HANDLE h2 = ::CreateThread(NULL, 0, Proc2, NULL, 0, NULL); ::CloseHandle(h2); InitializeCriticalSection(&cs1); InitializeCriticalSection(&cs2); while(1) { } DeleteCriticalSection(&cs1); return 0; }
全局变量X
全局变量Y
全局变量Z
线程1
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
EnterCriticalSection(&g_cs);
使用X
使用Y
LeaveCriticalSection(&g_cs);
return(0);
}
线程2
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
EnterCriticalSection(&g_cs);
使用X
使用Z
LeaveCriticalSection(&g_cs);
return(0);
}
线程3
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
EnterCriticalSection(&g_cs);
使用Y
使用X
LeaveCriticalSection(&g_cs);
return(0);
}
这样做会导致线程2在使用z的时候,线程1无法使用x;
解决方案:
CRITICAL_SECTION g_csX;
CRITICAL_SECTION g_csY;
CRITICAL_SECTION g_csZ;
线程1
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
EnterCriticalSection(&g_csX);
使用X
LeaveCriticalSection(&g_csX);
EnterCriticalSection(&g_csY);
使用Y
LeaveCriticalSection(&g_csY);
return(0);
}
线程2
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
EnterCriticalSection(&g_csX);
使用X
LeaveCriticalSection(&g_csX);
EnterCriticalSection(&g_csZ);
使用Z
LeaveCriticalSection(&g_csZ);
return(0);
}
线程3
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
EnterCriticalSection(&g_csX);
使用X
LeaveCriticalSection(&g_csX);
return(0);
}
#include <windows.h> #include<stdio.h> CRITICAL_SECTION cs1; int y; DWORD WINAPI Proc1(LPVOID lpParameter) { for(int i = 0; i < 1000; i++) { Sleep(1000); EnterCriticalSection(&cs1); printf("1++++++++++:%d ", ++y); ExitThread(2); LeaveCriticalSection(&cs1); } return 0; } DWORD WINAPI Proc2(LPVOID lpParameter) { for(int i = 0; i < 1000; i++) { Sleep(1000); EnterCriticalSection(&cs1); printf("2----------:%d ", ++y); LeaveCriticalSection(&cs1); } return 0; } int main(int argc, char* argv[]) { HANDLE h1 = ::CreateThread(NULL, 0, Proc1, NULL, 0, NULL); ::CloseHandle(h1); HANDLE h2 = ::CreateThread(NULL, 0, Proc2, NULL, 0, NULL); ::CloseHandle(h2); InitializeCriticalSection(&cs1); while(1) { } DeleteCriticalSection(&cs1); return 0; }
使用临界区当一个线程领走令牌后没有归还令牌前,如果线程意外终止,那么另一个使用相同令牌的临界区线程就会一直卡死不运行,因为被终止的线程没有归还令牌。