windows线程同步
一、前言
之前在项目中,由于需要使用到多线程,多线程能够提高执行的效率,同时也带来线程同步的问题,故特此总结如下。
二、windows线程同步机制
windows线程同步机制常用的有几种:Event、Critical Section、Mutex、Semaphore。
1.Critical Section(临界区)
适用范围: 单一进程的各线程之间用来排它性占有
特性: 不是内核对象,是这里提到的四种机制中速度效率最高的(注意:由于临界区是非内核对象,可在用户空间维护,则无句柄,那么就不能使用WaitForMultipleObjects防止死锁的问题了)。无法监测是否被线程放弃。如果在Critical Sections中间突然程序crash或是exit而没有调用LeaveCriticalSection,则结果是该线程所对应的内核不能被释放,该线程成为死线程。
临界区相关函数:
VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); //函数功能初始化一个临界资源对象。
VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); // 进入临界区
VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); // 离开临界区
VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); // 销毁临界区
2.Mutex(互斥内核对象)
适用范围: 不同线程之间用来排它性占有
特性: 核心对象,有句柄,有拥有者,哪个线程拥有mutex,就占有mutex的所有权,非拥有者执行ReleaseMutex会出错。mutex可以跨进程同步。
互斥量相关函数:
a.创建
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, //安全属性结构指针
BOOL bInitialOwner, //是否占有该互斥量
LPCTSTR lpName //设置互斥对象的名字
);
b.打开一个现有命名互斥量
HANDLE OpenMutex(
DWORDdwDesiredAccess, // access
BOOLbInheritHandle, // inheritance option
LPCTSTRlpName // object name
);
c.占有/获取互斥量
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
d.释放互斥量
BOOL WIANPI ReleaseMutex(
HANDLE hMutex
);
3.Event(事件内核对象)
适用范围: 用来控制对象信号的接收,常与信号系统结合起来
特性: 核心对象,有句柄,有两种不同类型的事件对象。一种是人工重置的事件,另一种是自动重置的事件。当人工重置的事件得到通知时(signaled),等待该事件的所有线程均变为可调度线程,直到调用ResetEvent,事件才会变为unsignaled。当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程,事件则自动变为unsigned。
SetEvent后,自动置位事件则会保持状态,直到有等待事件的,之后自动复位。手动复位事件,则保存signaled状态直到调用ResetEvent。
PulseEvent后,对于手动复位事件,所有当前线程(如果有的话)会得到释放,而后事件会被复位为unsigned。(不建议使用)
WaitForMultipleObjects,只有当所有等待的事件同时处于signaled,才会释放,对于自动复位的事件在线程释放后自动复位。
相关函数:CreateEvent, OpenEvent,SetEvent, ResetEvent, PulseEvent。
4.Semaphore(信号内核对象)
适用范围: 用来限制资源占用
特性: 核心对象,没有拥有者,任何线程都可释放。信号量(Semaphore)内核对象对线程的同步方式与前面几种方法不同,它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。在用 CreateSemaphore()创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数就会减1,只要当前可用资源计数是大于0的,就可以发出信号量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目,不能在允许其他线程的进入,此时的信号量信号将无法发出。线程在处理完共享资源后,应在离开的同时通过 ReleaseSemaphore()函数将当前可用资源计数加1。在任何时候当前可用资源计数决不可能大于最大资源计数。
函数: CreateSemaphore OpenSemaphore ReleaseSemaphore
三、对比
Mutex与Critical Section对比
1.Mutex如果被终止线程所泛起,会是已传信的,其他线程不会永远阻塞;而Critical Section则不是,如果被终止线程没有释放,那么其他等待线程将永远阻塞。
2.Mutex是内核对象,,有超时机制(有句柄,可以是使用WaitFor_函数实现);而CS非内核对象,无句柄,不能使用WaitFor系列函数,实现超时机制,只能使用TryEnterCriticalSection轮询。
3.Mutex可命名,可以跨进程同步,CS不行。
4.Mutex可在创建时,立即指定对该mutex的拥有权,CS没有不行。
5.CS由于是非内核对象,不需要频繁的切换程序运行的状态到核心态下,所有CS几乎总是比Mutex要快。
非内核对象(CS)与内核对象(其他的)对比:
1.内核对象有句柄能使用WaitForMultipleObjects,一次等待多个对象,避免死锁;
2.CS无句柄,不能使用,需要自己考虑防止死锁的问题。(给CS编号,按照一定顺序获取,打破形成环)。
3.对于上面几种命名的内核同步对象,可以进行跨进程同步;而,CS是非内核对象,直接建构在用户空间下,速度快的同时带来另一个问题,那就是没有办法跨进程同步。
四、后记
对于CS的使用,我们一般使用内部类的形式,防止异常的时候没有LeaveCriticalSection。
这个可能总结不够全,希望以后能够进行总结。另外该博文参考了http://www.cnblogs.com/luxiaoxun/archive/2012/10/10/2717765.html
windows线程同步的更多相关文章
- windows线程同步的总结
一 线程 1)如果你正在编写C/C++代码,决不应该调用CreateThread.相反,应该使用VisualC++运行期库函数_beginthreadex,退出也应该使用_endthreadex.如果 ...
- 关于windows线程同步的四种方法
#include "stdafx.h" #include "iostream" #include "list" #include " ...
- Windows线程同步(下)
线程同步三:事件 CreateEvent:Creates or opens a named or unnamed event object. HANDLE WINAPI CreateEvent( _I ...
- Windows线程同步(上)
先介绍一个创建线程的API,参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx ...
- windows线程同步的几种方式
以下为main函数的测试代码 具体线程同步的实现代码请下载:https://github.com/kingsunc/ThreadSynchro #include <stdio.h> #in ...
- windows 线程同步
Windows 临界区,内核事件,互斥量,信号量. 临界区,内核事件,互斥量,信号量,都能完成线程的同步,在这里把他们各自的函数调用,结构定义,以及适用情况做一个总结. 临界区: 适用范围:它只能同步 ...
- 总结windows多线程同步互斥
windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...
- Windows线程+进程通信
一 Windows线程进程 1)定义 按照MS的定义, Windows中的进程简单地说就是一个内存中的可执行程序, 提供程序运行的各种资源. 进程拥有虚拟的地址空间, 可执行代码, 数据, 对象句柄集 ...
- 操作系统中的进程同步与Window中利用内核对象进行线程同步的关系
操作系统中为了解决进程间同步问题提出了用信号量机制,信号量可分为四种类型分别是互斥型信号量,记录型信号量,AND型信号量,信号量集. 互斥型信号量 互斥型信号量是资源数量为1的特殊的记录型信号量.表示 ...
随机推荐
- Nginx + Tomcat 动静分离实现负载均衡(转)
0.前期准备 使用Debian环境.安装Nginx(默认安装),一个web项目,安装tomcat(默认安装)等. 1.一份Nginx.conf配置文件 # 定义Nginx运行的用户 和 用户组 如果对 ...
- Hadoop以及其外围生态系统的安装参考
在研究Hadoop的过程中使用到的参考文档: 1.Hadoop2.2 参考文档 在CentOS上安装Hadoop 2.x 集群: http://cn.soulmachine.me/blog/201 ...
- SQL Server 之 DBCC
--检查索引碎片情况 dbcc showconfig(tablename) 具体例子: --上图为碎片整理之前 ALTER INDEX ALL on Citation REBUILD --下图为碎片整 ...
- Scrum敏捷开发简介
Agile 敏捷开发实践中,强调团队的自我管理.在 Scrum 中,自我团队管理体现在每天的 Scrum 会议中和日常的协同工作,在每天的 Scrum 例会中,团队成员一般回答一下几个问题 : 昨天完 ...
- hdu 4699 Editor 模拟栈
思路:刚开始用STL中的栈,一直RE……,之后改为手动模拟栈操作,在注意点细节就可以了!!! 代码如下: #include<cstdio> #include<cstring> ...
- hdu 3923 Invoker
完全是套用polya模版…… ;}
- SQL SERVER(MSSQLSERVER) 服务无法启用 特定服务错误:126
SQL SERVER(MSSQLSERVER) 服务无法启用 特定服务错误:126 对于这样一个错误google了一下 说是 要禁止掉via才行 回到SQL配置管理器中 禁止掉via 果然可以重新 ...
- Git stash方法(转)
命令:git stash1.使用git stash保存当前的工作现场,那么就可以切换到其他分支进行工作,或者在当前分支上完成其他紧急的工作,比如修订一个bug测试提交. 2.如果一个使用了一个git ...
- HtmlAgilityPack 总结(一)
一个解析html的C#类库HtmlAgilityPack, HtmlAgilityPack是一个基于.Net的.第三方免费开源的微型类库,主要用于在服务器端解析html文档(在B/S结构的程序中客户端 ...
- ubuntu -LDAP的配置
本文内容来自 http://blog.csdn.net/jl19861101/article/details/5582841 1. LDAP Server1.1. 安装主要安装一下套件: 代码: # ...