Windows提高_2.3第三部分:内核区同步
2024-08-30 23:42:45
第三部分:内核区同步
等待函数(WaitForObject)
等待函数的形式
单个:WaitForSingleObject
多个:WaitForMultipleObjects
一个可以被等待的对象通常由两种状态,分别是:
可等待(激发态)(有信号):等待函数【不会阻塞】
不可等待(非激发态)(无信号):等待函数需要等待一定时长并【阻塞】
等待函数的副作用:
改变被等待对象的信号状态
#include <iostream>
#include <windows.h>
// 工作线程
DWORD WINAPI WorkerThread(LPVOID lpThreadParameter)
{
// 输出 0 ~ 99
for (int i = ; i < ; ++i)
{
printf("%d\n", i);
}
return ;
}
int main()
{
HANDLE Threads[] = { };
// 创建两个线程
Threads[] = CreateThread(NULL, NULL, WorkerThread, NULL, NULL, NULL);
Threads[] = CreateThread(NULL, NULL, WorkerThread, NULL, NULL, NULL);
Threads[] = CreateThread(NULL, NULL, WorkerThread, NULL, NULL, NULL);
// 函数返回的两种情况
// 1. 被等待对象处于有信号状态
// 2. 等到超时函数会返回,但是等待失败
// 等待两个线程退出
// 1. 一个可以被等待的内核对象
// 2. 等待时长,如果是-1 表示一直等待
// WaitForSingleObject(ThreadHandles[0], INFINITE);
// WaitForSingleObject(ThreadHandles[1], INFINITE);
// 等待多个内核对象
// 1. 需要等待多少个内核对象
// 2. 内核对象句柄的数组
// 3. 是否等待所有内核对象编程变成有信号的
// 4. 等待的时长,单位是毫秒
// WaitForMultipleObjects(2, ThreadHandles, TRUE, INFINITE);
// 有任何一个执行完毕,另外一个就不执行了
WaitForMultipleObjects(, Threads, FALSE, INFINITE);
// 等待函数的副作用:修改被等待对象的信号状态
return ;
}
互斥体(Mutex)
特点:拥有临界区的线程拥有者概念,但是线程崩溃不会死锁,执行较慢
函数
创建:CreateMutex,如果第二个参数是FALSE,那么就是可等待
打开:OpenMutex
保护:WaitForSingleObject: 把互斥体置为不可等待
释放:ReleaseMutex把互斥体置为可等待
关闭:CloseHandle
// 1. 创建一个互斥体内核对象
// - 安全属性,初始状态,名称
HANDLE Mutex = CreateMutex(NULL, FALSE, L"Mutex");
DWORD WINAPI ThreadPro1(LPVOID lpThreadParameter)
{
// 为 g_Number 自增 100000 次
for (int i = ; i < ; i++)
{
// 2. 使用等待函数对互斥体进行等待,当互斥体处于激发态就会等待成功
// 当等待成功时,会将互斥体置为无信号状态
WaitForSingleObject(Mutex, INFINITE);
g_Number++;
// 3. 执行完代码之后需要恢复有信号状态
ReleaseMutex(Mutex);
}
return ;
}
事件(Event)
特点:可以手动选择是否产生副作用,如果设置为手动状态,那么就不产生副作用
函数:
创建:CreateEvent()
打开:OpenEvent()
保护:WaitForSingleObject()
设置为非激发态:ResetEvent()
退出(设置为激发态):SetEvent()
关闭:CloseHandle
// 1. 创建一个事件内核对象
// - 安全属性,是否自动,初始状态,名称
HANDLE Event = CreateEvent(NULL, FALSE, TRUE, L"Event");
// HANDLE Event = CreateEvent(NULL, TRUE, TRUE, L"Event");
DWORD WINAPI ThreadPro1(LPVOID lpThreadParameter)
{
// 为 g_Number 自增 100000 次
for (int i = ; i < ; i++)
{
// 注意:如果使用手动模式,等待函数就没有副作用
// 可以使用 ResetEvent 手动设置信号状态,但是没有意义
// 原因是 ResetEvent 本身不是一个原子操作
// 2. 使用等待函数对事件进行等待,当事件处于激发态就会等待成功
// 当等待成功时,会将事件置为无信号状态
WaitForSingleObject(Event, INFINITE);
g_Number++;
// 3. 执行完代码之后需要恢复有信号状态
SetEvent(Event);
}
return ;
}
信号量
特点:有多把锁,可以控制活动线程的数量,没有线程拥有者概念。
如果锁的最大个数是1,则用法和互斥体类似
函数:
创建:CreateSemaphore
打开:OpenSemaphore
上锁:WaitForSingleObject
解锁:ReleaseSemaphore
关闭:CloseHandle
// 1. 创建一个信号量内核对象
// - 安全属性,当前信号,最大信号,名称
HANDLE Semaphore = CreateSemaphore(NULL, , , L"Semaphore");
DWORD WINAPI ThreadPro1(LPVOID lpThreadParameter)
{
// 为 g_Number 自增 100000 次
for (int i = ; i < ; i++)
{
// 2. 使用等待函数对信号量进行等待,当信号个数>1表示可等待
// 当等待成功时,会将信号个数 -1
WaitForSingleObject(Semaphore, INFINITE);
g_Number++;
// 3. 执行完代码之后需要将信号个数 +1
// 信号量对象,+几个信号,之前有多少个信号
ReleaseSemaphore(Semaphore, , NULL);
}
return ;
}
最新文章
- c#修改config中的AppSettings属性
- C#学习笔记 -- Attribute
- Centos6.7 python2.6升级到python2.7
- 【PHP入门到精通】:Ch05:字符串处理
- 使用jQuery-AJAX–读取获得跨域JSONP数据的示例
- WPF WebBrowser
- 【UVA11019】Matrix Matcher
- Android -------- 序列化器生成xml文件
- css3之background
- 布局神器:Flexbox
- java 区分error和exception
- 大数据OLAP引擎对比
- tensorflow笔记6:tf.nn.dynamic_rnn 和 bidirectional_dynamic_rnn:的输出,output和state,以及如何作为decoder 的输入
- (转)Lua学习笔记1:Windows7下使用VS2015搭建Lua开发环境
- PostgreSQL ALTER TABLE中改变数据类型时USING的用法<;转>;
- iOS UTI(统一类型标识)
- javaAgent 参数
- PE结构详解
- RMAN Recovery Catalog
- Silver Cow Party
热门文章
- script标签async和defer的区别及作用
- .net mvc4 + ajaxfileupload.js 解决IE浏览器中弹出下载对话框问题
- 《炉石传说》架构设计赏析(4):Asset管理
- TMS320F28335项目开发记录6_28335之cmd文件具体解释
- HDU4403 A very hard Aoshu problem DFS
- Message: SyntaxError: unterminated string literal
- ios20--xib2
- 同一个站点下,兼容不同版本的JQuery
- presentModalViewController和dismissModalViewControllerAnimated的使用总结
- C# WINFORM 窗体执行ORACLE存储过程 进行增删改查 自己编写借助网络(二)