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的特殊的记录型信号量.表示 ...
随机推荐
- C语言基础:数组和字符串
数组:数组的定义注意点 数组初始化正确写法: int args[5] = {1,23,32,4,5}; int args[5] = {12,23}; int args[5] = {[3]=23, [4 ...
- bug集合
解决方法:vertical-align:top; 垂直对齐方式:对浮动元素无效浮动类: ie 6 7要在一行显示多个div要 给每一个元素浮动 否则会出间隙. ie6双倍边距bug 1. bug条件 ...
- Linux查看系统基本信息
问题描述: 查看系统基本信息 问题解决: (1)lspci 是一个用来显示系统中所有PCI总线设备或连接到该总线上的所有设备的工具. 用法: lspci -v (1.1) ...
- 【转载】C++中结构体的声明和定义
http://blog.csdn.net/whuslei/article/details/5665289 1 //定义一个结构体,类型为struct Student 2 struct Stude ...
- httpsClient
Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且 ...
- unity3d android互调
unityPlayer = new AndroidJavaClass("com.xxx.xxx.MainActivity"); curActivity = unityPlayer. ...
- hdu 1180 诡异的楼梯
诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Subm ...
- Fragment 与 Activity 通信
先说说背景知识: (From:http://blog.csdn.net/t12x3456/article/details/8119607) 尽管fragment的实现是独立于activity的,可以被 ...
- lintcode :sort letters by case字符大小写排序
题目 字符大小写排序 给定一个只包含字母的字符串,按照先小写字母后大写字母的顺序进行排序. 您在真实的面试中是否遇到过这个题? Yes 样例 给出"abAcD",一个可能的答案为& ...
- lintcode 中等题:unique Binary Search Tree 不同的二叉查找树
题目 不同的二叉查找树 给出 n,问由 1...n 为节点组成的不同的二叉查找树有多少种? 样例 给出n = 3,有5种不同形态的二叉查找树: 1 3 3 2 1 \ / / / \ \ 3 2 1 ...