win32(十五)
来源:互联网 发布:淘宝怎么用余额宝分期 编辑:程序博客网 时间:2024/05/17 06:13
一 线程局部存储 Thread Local Storage 1 由于多个线程使用同一个变量,各个线程 都对变量进行操作,那么变量的值会被不同 线程操作覆盖。 通常 变量A <-- 线程A <-- 线程B TLS 变量A <-- 线程A 变量A <-- 线程B 2 TLS的使用 2.1 使用关键字 __declspec(thread) __declspec(thread) CHAR * g_pszText2 = NULL; 2.2 TLS相关API 2.2.1 创建TLS索引 DWORD TlsAlloc(VOID) 返回一个TLS索引号 2.2.2 设置值 BOOL TlsSetValue( DWORD dwTlsIndex, //TLS索引 LPVOID lpTlsValue //保存的值 ); 2.2.3 获取值 LPVOID TlsGetValue( DWORD dwTlsIndex //TLS索引 ); 返回存放在索引内的值 2.2.4 释放 BOOL TlsFree( DWORD dwTlsIndex //TLS索引 );二 线程同步 1 多线程的问题 A停止 -> B开始 -〉B停止 -> A开始 当线程停止会保存寄存器的状态。 当线程开始会恢复寄存器的状态。 AB线程都使用printf的问题: A线程调用printf时,printf正在输出 当中,A挂起,B执行,B线程也调用 printf输出B的数据,画面会出现A的 数据输出1部分,然后是B的数据; B挂起,A执行, A继续输出自己的数据. 所以,由于多线程的切换,产生数据混乱. 2 问题的解决 - 同步机制 2.1 原子锁 2.2 临界区 2.3 事件 2.4 互斥 2.5 信号量 2.6 可等候定时器 3 等候多个内核对象事件 DWORD WaitForMultipleObjects( DWORD nCount,//句柄的数量 CONST HANDLE *lpHandles,//句柄数组 BOOL fWaitAll, //等候方式 DWORD dwMilliseconds );//等候时间 等候方式fWaitAll: TRUE - 每个句柄都有事件,解除阻塞 FALSE - 其中一个句柄有事件,解除阻塞三 原子锁 1 g_nValue++执行 线程A通过寄存器完成加法运算,假设 g_nValue正在加到10000时,线程切换到B, A的寄存器中保存10000数字,B从10000 开始加数据,当B加到15000时,线程切换 到A,A恢复寄存器的值,A会继续从10000开始 累加,就将B完成5000的加法覆盖. 2 原子锁 执行单个指令时,锁定操作,不允许其他 线程访问. 3 用法 InterlockedIncrement ++运算 InterlockedDecrement --运算 InterlockedCompareExchange ?运算四 临界区 1 临界区作用 线程在执行代码时,将代码锁定,不允 许其他线程执行,只有该线程离开后, 其他线程才能使用这些代码 2 临界区的使用 2.1 初始化临界区 VOID InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection //临界区结构地址 ); 2.2 临界区加锁 VOID EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection // pointer to critical //临界区 ); 2.3 临界区解锁 VOID LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection // 临界区 ); 2.4 释放临界区 VOID DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection //临界区 ); 3 和原子锁相比 原子锁是一条语句 临界区可以完成多条语句的锁定.五 事件 1 事件 通知的作用,当收到事件时,线程可以执行. 否则,线程将等候事件发生. 2 事件的用法 2.1 创建事件 HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, //安全属性 BOOL bManualReset,//重置方式 BOOL bInitialState, //初始化状态 LPCTSTR lpName //名称 ); 返回创建好的事件句柄 bManualReset - 事件重置方式, TRUE 手动和FALSE自动重置. 如果为FALSE, 系统在等候到事件后,会自动将事件 重置为无信号状态. 如果为TRUE,我们 必须自己使用ResetEvent重置状态. bInitialState - 初始化状态, TRUE为 有信号,FALSE无信号. 2.2 等候事件 WaitForSingleObject/ WaitForMultipleObjects 2.3 触发事件 BOOL SetEvent( HANDLE hEvent //事件句柄 ); 2.4 关闭事件 CloseHandle 2.5 重置事件 BOOL ResetEvent( HANDLE hEvent //事件句柄 ); 2.6 其他函数 OpenEvent PulseEvent六 互斥量 1 互斥量 多个线程同时只能有一个执行. 2 互斥量使用 2.1 创建互斥 HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, //安全属性 BOOL bInitialOwner, //初始化的拥有线程 LPCTSTR lpName ); //名称 bInitialOwner - TRUE表示当前创建互斥 量的线程拥有互斥, FALSE为不拥有. 2.2 等候互斥 WaitForSingleObject WaitForMultipleObjects 2.3 重置互斥 ReleaseMutex 2.4 关闭互斥 CloseHandle 2.5 使用互斥线程,按照谁先等候谁先 拥有互斥量的规则顺序执行. 2.6 其他函数 OpenMutex 打开互斥七 信号量 1 信号量 通知的作用,和事件类似.但是与事件不同. 事件只维护一个值0或者1. 信号量维护一个变量,0时无信号,大于0有 信号. 2 信号量的使用 2.1 创建信号量 HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, //安全属性 LONG lInitialCount,//初始信号量 LONG lMaximumCount,//最大信号量 LPCTSTR lpName //命名 ); 返回创建好的信号量句柄. 2.2 等候信号量 WaitForSingleObject WaitForMultipleObjects 2.3 释放信号 BOOL ReleaseSemaphore( HANDLE hSemaphore, //信号量句柄 LONG lReleaseCount,//释放信号的数量 LPLONG lpPreviousCount //释放前的数量 ); 2.4 关闭信号量 CloseHandle 2.5 打开信号量 OpenSemaphore八 可等候定时器 1 可等候定时器 是一个更加精确系统提供的定时器.能够 达到100ns级别. 2 定时器的使用 2.1 创建定时器 HANDLE CreateWaitableTimer( LPSECURITY_ATTRIBUTES lpTimerAttributes, //安全属性 BOOL bManualReset,//重置方式 LPCTSTR lpTimerName //命名 ); 返回创建好的定时器的句柄 2.2 设置定时器 BOOL SetWaitableTimer( HANDLE hTimer, //定时器句柄 const LARGE_INTEGER *pDueTime, //定时器第一次触发的时间,100ns级别 LONG lPeriod, //后续每次触发的间隔,毫秒级别 PTIMERAPCROUTINE pfnCompletionRoutine, //APC处理函数 LPVOID lpArgToCompletionRoutine, //APC参数 BOOL fResume ); //休眠标识 pDueTime - 正值,表示绝对时间 负值,表示相对于现在的时间间隔 lPeriod - 0 定时器不再有后续触发 大于0 按照间隔触发 pDueTime | lPeriod | lPeriod .... 2.3 等候定时器 WaitForSingleObject WaitForMultipleObjects 2.4 关闭定时器 CloseHandle 2.5 APC定时器 VOID CALLBACK TimerAPCProc( LPVOID lpArgToCompletionRoutine // data value DWORD dwTimerLowValue // timer low value DWORD dwTimerHighValue // timer high value ); 2.6 其他 OpenWaitableTimer 打开 CancelWaitableTimer 取消
0 0
- win32(十五)
- 随笔(十五)
- 程序人生(十五)
- CSS 列表(十五)
- 十五周(一)
- 学习笔记(十五)
- 读书笔记(十五)--将才
- 创业笔记(十五)
- linux命令行(十五)
- (孙鑫 十五)多线程
- WIX学习(十五)
- 东软实训(十五)
- 东软实训(二十五)
- 日拱一卒(十五)
- 日拱一卒(二十五)
- ios项目(十五)
- Scala练习(十五)
- (十五)换行
- win32(十四)
- SuperSwipeRefreshLayout 一个功能强大的自定义下拉刷新组件
- [微信JS-SDK]微信公众号JS开发之卡券领取功能详解
- Memcached之你真正理解LRU吗(4)
- linux下安装apache 及报错解答
- win32(十五)
- K&C 式样的函数定义
- mac下192.168.2.1引起的连接问题
- Ztree 相关.
- 合并两个递增的列表
- opencv 图片读写,截取,复制,标记
- 《算法导论》的基数排序 C++实现
- Linux centOS下修复“运行aclocal失败:没有该文件或目录”
- 《HTTP权威指南》阅读笔记(七)