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函数,否则会一直递增导致死锁






 本文转自超级极客51CTO博客,原文链接:http://blog.51cto.com/12158490/1950808,如需转载请自行联系原作者




相关文章
|
5月前
|
C++ 运维
开发与运维编译问题之在C++中在使用std::mutex后能自动释放锁如何解决
开发与运维编译问题之在C++中在使用std::mutex后能自动释放锁如何解决
74 2
|
4月前
|
算法 Java 调度
【多线程面试题二十】、 如何实现互斥锁(mutex)?
这篇文章讨论了在Java中实现互斥锁(mutex)的两种方式:使用`synchronized`关键字进行块结构同步,以及使用`java.util.concurrent.locks.Lock`接口进行非块结构同步,后者提供了更灵活的同步机制和扩展性。
|
7月前
|
安全 算法 Linux
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(下)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(下)
|
7月前
|
存储 Linux 程序员
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(中)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(中)
|
7月前
|
缓存 Linux 调度
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(上)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(上)
|
7月前
|
算法 安全 C++
【C++入门到精通】互斥锁 (Mutex) C++11 [ C++入门 ]
【C++入门到精通】互斥锁 (Mutex) C++11 [ C++入门 ]
60 0
|
Java 调度 C++
C++并发与多线程(五)互斥量,atomic、与线程池(下)
C++并发与多线程(五)互斥量,atomic、与线程池(下)
107 0
|
7月前
|
安全 C++ 开发者
【C++多线程同步】C++多线程同步和互斥的关键:std::mutex和相关类的全面使用教程与深度解析
【C++多线程同步】C++多线程同步和互斥的关键:std::mutex和相关类的全面使用教程与深度解析
98 0
|
7月前
|
前端开发 安全 C++
c++11线程、互斥量、条件变量等
c++11线程、互斥量、条件变量等
C++11/14/17中提供的mutex系列区别
C++11/14/17中提供的mutex系列类型如下: