VC++多线程同步(一) Mutex互斥量

一 、同步机制的引入目的是为了解决三个主要问题

1为了控制线程之间共享资源的同步访问,保证共享资源的完整性.(比如一个线程正在更新一个数据,而另外一个线程正在读取该数据,那么就不知道该数据是新的还是旧的,为了避免这种状况的发生)

2确保线程之间的动作,以制定的次序发送,例如一个线程的触发,需要另外一个线程的结果,作为条件。

3为了控制某一个共享资源的最大访问量,例如我们同时只能处理5个客户的请求,这时候,我们需要放到队列进行等待。

二、同步概念就是等待

WIN32  提供了API 等待函数

DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);

参数1 :hHandle对象句柄. 可以制定一系列的对象,如

Event(事件),Mutex(互斥),Seamphore(信号)Thread(线程)等

参数2:dwMilliseconds 定时时间间隔 单位milliseconds(毫秒)

1如果指定一个非零值,函数处于等待状态,直到hHandle标记的对象被触发,  或者时间到了.

2如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它立即返回.

3如果dwMilliseconds为INFINITE,对象被触发,信号,函数才会返回,大部分情况下只使用INFINITE这个宏.

这个函数是一个堵塞的函数,意味着,只有这个函数运行完成才进行返回.因此他是一个同步的函数.

返回值:

DWORD dw = WaitForSingleObject(hProcess,5000)

{

//在指定之间内,代表等待成功,触发了对象。

case WAIT_OBJECT_0:

//相应操作

break;

//等待时间结束,对象没触发,没有成功 说明超时了

case WAIT_TIMEOUT:

//相应操作

break;

//发生了一些错误 ,可以线程句柄是NULL

case WAIT_FAILED:

//相应操作

break;

}

三、Mutex互斥量对象(同步对象)

作用:

1 用于确保一个线程独占对于一个资源的访问

2 包含一个使用计数器,线程ID,以及一个递归计数

3 线程的id用来标识当前占用这个互斥量的是系统中的哪个线程

4 递归计数器表示这个线程占用该互斥量的次数

5 互斥量是使用最为频繁的内核对象之一

主要是当某个共享资源被某个,线程进行加锁操作后,其他的线程就无法访问该资源,进行读写.

1创建互斥量对象:

CreateMutex函数功能是建立互斥体对象,返回的就是这个对象

HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, //指向安全属性的指针

BOOL bInitialOwner //初始化互斥对象所有者

LPCTSTR lpName //指向互斥对象名的

)

参数1正常情况下使用NULL,如果我们使用跨进错的访问。

参数2 通常为FALSE,那么线程ID和递归计数器,都被设置为0.

参数3 指定互斥体对象名字,如果以及存在拥有这个,名字的一个事件,则打开现有的已命名互斥体,这个名字可能不予现有的事件,信号机,可等待计时器或文件映射相符。

通常用法:HANDLE Mutex = CreateMutex(NULL,FALSE,NUKL);

2释放互斥量对象:

ReleaseMutex函数

BOOL WINAPI ReleaseMutex(

HANDLE hMutex);

hMutex: 互斥对象的句柄

作用:这个函数会将对象的递归计数器减1,如果线程成功的等待了互斥量对象不止一次,那么线程必须调用release相同的次数

才能使对象的递归计数器变为0.当递归计数器为0时,函数还将线程ID设为0,使互斥量处于触发状态.

我们发现互斥量对象的递归计数器和id创建的时候就是0(也就是处于触发状态),那什么时候会增加使他非触发状态.

3整个互斥量的操作流程:  (加锁和解锁流程)

假设:有一个全局的文件指针,同时又有多个线程,需要对该文件 指针进行读写,但是,为了保证资源的完整性,我们在同一时刻,

只允许一个线程进行读写操作。

加锁:

为了获得对被保护的资源的访问权,线程要调用一个等待函数并转入前面创建的互斥量句柄,在内部,等待函数会检查线程ID是否为0(如果为0也就是触发状态)如果为0,那么函数会把互斥量句柄中的线程ID设为当前调用线程的ID,(只有这个加锁的线程,才

允许对资源进行读写访问操作 。)并把递归计数器设为1,此时

互斥量就处于非触发状态,对互斥量的线程id赋值和递归计数器增加,都是原子操作的,所谓的原子操作,就是指操作系统保证在完成原子操作之前,不进行线程的切换,然后当前线程继续运行。

解锁:

假设某一个线程成功的得到了互斥量,线程就知道自己独占了对受保护的资源的访问权, 那么任何视图通过等待互斥量,来获得

对资源的访问权的线程,将进入等待状态,很重要的一点是:当线程进入等待状态后,是不消耗Cpu时钟频率的.当独占线程对资源

操作完后, 必须调用ReleaseMutex函数(释放)来将互斥量的递归计数器减1 ,如果递归计数器的值为0的话,那么还会将线程id

设置为0,这样互斥量又处于触发状态了。

互斥量的注意点:

1线程id和递归计数器递增只能在wait(等待)函数中操作.

2必须要调用release函数,否则会一直递增导致死锁。

时间: 2024-10-27 19:47:19

VC++多线程同步(一) Mutex互斥量的相关文章

VC++线程同步(二) Mutex互斥量的例子

同步对象使用实例 Win32窗口的建立: 我们将要学习的使用,分别是:互斥量,临界区,事件,信号量.所以我们需要一个窗口,呈现四种四种同步对象状态. 首先创建一个Win32项目,不要选空项目; 我们需要四个小窗口,先找到注册主窗口的代码. ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style= CS_HREDRAW | CS_VREDRAW

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

线程同步方式之互斥量Mutex

互斥量和临界区非常相似,只有拥有了互斥对象的线程才可以访问共享资源,而互斥对象只有一个,因此可以保证同一时刻有且仅有一个线程可以访问共享资源,达到线程同步的目的. 互斥量相对于临界区更为高级,可以对互斥量进行命名,支持跨进程的线程同步.互斥量是调用的Win32的API对互斥锁的操作,因此在同一操作系统下不同进程可以按照互斥锁的名称共享锁. 正因为如此,互斥锁的操作会更好资源,性能上相对于临界区也有降低,在使用时还要多斟酌.对于进程内的线程同步使用临界区性能会更佳. 在.Net中使用Mutex类来

c# Thread5——线程同步之基本原子操作。Mutex互斥量的使用

之前的博文也说到了如果多线程对于访问的公共资源操作都是原子操作,那么可以避免竞争条件.关于多线程的竞争可以百度. 1.执行最基本的原子操作 c#提供了一系列供我们使用的原子操作的方法和类型,比如我们的自增和自减操作. 看代码 class Program { private static int _count = 0; static void Main(string[] args) { var thread1 = new Thread(() => { for(int i = 0; i < 100

【Linux】Mutex互斥量线程同步的例子

0.互斥量  Windows下的互斥量 是个内核对象,每次WaitForSingleObject和ReleaseMutex时都会检查当前线程ID和占有互斥量的线程ID是否一致. 当多次Wait**时就要对应多次ReleaseMutex, 当ReleaseMutex过多次数时如果发现当前占有互斥量的线程ID和当前调用ReleaseMutex的线程ID不一致时仅仅返回FLASE,GetLastError返回ERROR_NOT_OWNER,没有其他副作用. 当占有mutex的线程在Release之前退

windows多线程(六) 互斥量Mutex与关键段CriticalSection比较

一.关键段CS 和 互斥量Mutex 的相同点:都有线程拥有权 关键段和互斥量都有线程拥有权,即可以被一个线程拥有.在 前面讲关键段CS的文章中有说到,关键段结构体的第四个参数保存着拥有该关键段的线程的句柄,具体如下: typedef struct _RTL_CRITICAL_SECTION { PRTL_CRITICAL_SECTION_DEBUG DebugInfo; // // The following three fields control entering and exiting

Delphi多线程编程(10)--多线程同步之Mutex(互斥对象)

原理分析: 互斥对象是系统内核对象,各个线程都可以拥有它,谁拥有它谁就可以执行 执行完毕,用ReleaseMutex 函数释放拥有权,以让其他等待的线程可以使用 其他线程可以使用 WaitForSingleObject函数排队等待(等待也可以理解为排队申请) 使用过程 var hMutex: THandle; {应该先声明一个全局的互斥句柄} CreateMutex {建立互斥对象} WaitForSingleObject {用等待函数排队等候} ReleaseMutex {释放拥有权} Clo

Linux多线程同步之相互排斥量和条件变量

1. 什么是相互排斥量 相互排斥量从本质上说是一把锁,在訪问共享资源前对相互排斥量进行加锁,在訪问完毕后释放相互排斥量上的锁. 对相互排斥量进行加锁以后,不论什么其它试图再次对相互排斥量加锁的线程将会被堵塞直到当前线程释放该相互排斥锁.假设释放相互排斥锁时有多个线程堵塞,所以在该相互排斥锁上的堵塞线程都会变成可进行状态.第一个变成执行状态的线程能够对相互排斥量加锁.其它线程在次被堵塞,等待下次执行状态. pthread_mutex_t 就是POSIX对于mutex的实现. 函数名 參数 说明 p

转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数