1.互斥量
/*
*用于保护全局变量、硬件端口、管道识别码、窗口客户区
*多个线程共享资源时,优先考虑互斥量
*Mutex 可以跨进程使用,所以其名称对整个系统而言是全局的
*param1:安全特征,可以指定,也可以不填
*param2:线程所有权,设置为TRUE,调用方立即获得互斥量所有权
*param3:互斥量名称必须指定
*/此处若把参数2设置为TRUE,即创建线程互斥量,当前线程即获取该互斥量,需在同一个线程释放 h_Mutex = CreateMutex(NULL, FALSE, "mutex");
/*
*为现有的已经存在的互斥量对象创建一个新句柄
*param1:请求访问方式 安全特征
* MUTEX_ALL_ACCESS 请求对互斥体的完全访问
* MUTEX_MODIFY_STATE 允许使用 ReleaseMutex 函数
* SYNCHRONIZE 允许互斥体对象同步使用
*
*param2:如希望子进程能够继承句柄,则为TRUE
*param3:要打开对象的名字
*互斥量不存在返回失败ERROR_FILE_NOT_FOUND 必须释放互斥量ReleaseMutex
*/HANDLE ret = OpenMutex(MUTEX_ALL_ACCESS, TRUE, "mutex");
等待互斥量
WaitForSingleObject(h_Mutex, INFINITE);//等待互斥量
释放互斥量
BOOL ret = ReleaseMutex(h_Mutex);
2.信号量
/*
*用于保护全局变量、硬件端口、管道识别码、窗口客户区
*多个线程共享资源时,优先考虑互斥量
*Semaphores 可以跨进程使用,所以其名称对整个系统而言是全局的
*param1:安全特征,可以指定,也可以不填 NULL默认安全方式
* MUTEX_ALL_ACCESS 请求对互斥体的完全访问
* MUTEX_MODIFY_STATE 允许使用 ReleaseMutex 函数
* SYNCHRONIZE 允许互斥体对象同步使用
*param2:初始数目以确定信号量初始触发状态,设置为0,为未触发状态,如果当前资源计数等于0,那么信号量处于未触发状态;那么系统会让调用线程进入等待状态
*param3:可同时持有信号量所有权的最多线程对象数目
*param4:必须提供信号量名
*/创建信号量
h_Semaphore = CreateSemaphore(NULL, 0, 1, "semaphore");
等待信号量
WaitForSingleObject(h_Semaphore, INFINITE);//等待互斥量
释放信号量
BOOL ret = ReleaseSemaphore(h_Semaphore, 1, NULL);
3.事件对象
/*
*param1:安全特征,可以指定,也可以不填 NULL默认安全方式.确定返回的句柄是否可被子进程继承,是NULL,此句柄不能被继承
*param2:用于确定事件对象,TRUE代表必须把ResetEvent中事件对象设置为未触发状态.(TRUE)必须使用ResetEvent()手动重置为无信号状态
* FALSE当一个等待线程被释放时,自动重置状态为无信号状态
*param3:设置事件初始状态,为TRUE则表示立即设置为触发状态
*param4:必须提供事件名
*/创建事件对象
h_Event = CreateEvent(NULL, TRUE,TRUE,"event");
将事件对象设置为已触发状态
BOOL ret = SetEvent(h_Event);
将事件对象设置为未触发状态
BOOL ret = ResetEvent(h_Event);
脉冲事件,将事件对象设置为已触发状态,然后将其重置为未触发状态,释放特定数量的等待线程
BOOL ret = PulseEvent(h_Event);
事件对象在创建时候的四种情况分析,针对参数二和参数三
1.人工重置事件:使用手动重置为无信号状态,初始化时有信号状态,调用WaitForSingleObject不会等待
CreateEvent(NULL, TRUE, TRUE, NULL)
2.人工重置事件:使用手动重置为无信号状态,初始化时为无信号状态 调用WaitForSingleObject会一直等待
CreateEvent(NULL, TRUE, FALSE, NULL);
若某个线程调用WaitForSingleObject(hEvent,INFINITE) 则会一直等待,需要先调用SetEvent()设置为有信号状态,才能继续执行,否则一直在等待;ResetEvent(),要想有信号需调用SetEvent(hEvent)
3.自动重置事件:当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态,调用WaitForSingleObject不会等待
CreateEvent(NULL, FALSE, TRUE, NULL);
另一个线程若还需要等到通知,即在当前线程调用SetEvent()
4.自动重置事件:线程释放后自动重置为无信号状态,初始化时为无信号状态
CreateEvent(NULL, FALSE, FALSE, NULL);
4.临界区
临界区的功能与互斥量相同,同一时刻只被一个线程拥有
运行速度更快,开销更小
开始临界区对象处于未触发状态,被释放后处于触发状态临界区创建以及使用方式。
1.先声明临界区对象
2.初始化
3.让线程进入临界区
4.任务完成后,让线程离开临界区
5.释放资源//1
CRITICAL_SECTION c_section;
//2
InitializeCriticalSection(&c_section);
//3
EnterCriticalSection(&c_section); //或者 TryEnterCriticalSection(&c_section);
//4
LeaveCriticalSection(&c_section);
//5
DeleteCriticalSection(&c_section);