例子:记录线程调用顺序
#include <windows.h> #include <iostream> #include <vector> using namespace std; #define THREADCOUNT 9 CRITICAL_SECTION testCS; DWORD WINAPI ThreadFunc( LPVOID ); std::vector<int> orderVec; //记录线程调用顺序 int main( void ) { HANDLE aThread[THREADCOUNT]; DWORD ThreadID; int i; InitializeCriticalSection(&testCS); // Create worker threads for( i=0; i < THREADCOUNT; i++ ) { aThread[i] = CreateThread( NULL, // default security attributes 0, // default stack size ThreadFunc, //(LPTHREAD_START_ROUTINE) (LPVOID)i, // no thread function arguments 0, // default creation flags &ThreadID); // receive thread identifier } Sleep(100); for( i=0; i < THREADCOUNT; i++ ) CloseHandle(aThread[i]); int count = orderVec.size(); cout << " order of calling thread:"; for (int i=0; i<count; ++i) { cout << orderVec[i] << ", "; } DeleteCriticalSection(&testCS); system("pause"); return 0; } DWORD WINAPI ThreadFunc( LPVOID lpParam ) { //如果不加临界区 vector.push_back操作可能中途被打断 出现错误 EnterCriticalSection(&testCS); int i = (int)lpParam; orderVec.push_back(i); LeaveCriticalSection(&testCS); return TRUE; }
结果:
order of calling thread:0, 1, 2, 4, 5, 3, 7, 6, 8, 请按任意键继续. . .
InitializeCriticalSection function
初始化一个临界区对象
void WINAPI InitializeCriticalSection(
_Out_ LPCRITICAL_SECTION lpCriticalSection
);
参数
lpCriticalSection [out]
指向临界区对象的指针
注意
单进程中的线程可以使用临界界对象来解决青互斥同步问题。但不保证线程得到临界区对象的顺序,系统公平对待每个线程。进程负责为临界区对象分配内存。即定义一个类型为CRITICAL_SECTION变量。在使用临界区对象之前,进程中的线程必须初始化临界区对象。在临界区对象初始化之后,线程可以使用函数EnterCritical TryEnterCriticalSection或LeaveCriticalSection函数来互斥地访问共享资源。在不同进程中的线程同步,可以使用mutex对象。
临界区对象不能被移动,也不能被复制。进程不能修改临界区对象,但这是不符合逻辑的。只能使用临界区函数管理临界区对象。当你想结束一个临界区对象时,调用DeleteCriticalSection函数。
在重新初始化临界区对象之前,临界区对象必须被删除。初始化一个已经初始化的临界区对象,结果是未知的。