线程同步-用内核对象进程线程同步

线程同步的几种方法

使用内核对象

1:事件对象

事件对象分为两种

当一个手动重置事件对象被触发时 正在等待该事件的素有线程都将变成可调度的状态( 一旦有信号被触发 所有等待线程都将往下执行)

而当一个自动重置事件对象被触发的时候,只有一个证在等待该事件的线程会变成可调度状态(一旦有信号被触发,只有一个等待线程会往下执行 再有信号被触发时 会再有另外一个线程往下执行)

 

 

WaitForSingleObject等待到一个手动重置事件对象信号的之后 要希望事件对象再变为无信号状态  需要调用ResetEvent  

而当等待到一个自动重置事件对象的之后 会自动将事件对象设为无信号状态 无需调用ResetEvent  

Event Function

Description

CreateEvent

Creates or opens a named or unnamed event object.

OpenEvent

Opens an existing named event object.

PulseEvent

Sets the specified event object to the signaled state and then resets it to the nonsignaled state after releasing the appropriate number of waiting threads.

ResetEvent

Sets the specified event object to the nonsignaled state.

SetEvent

Sets the specified event object to the signaled state.

 

 

2:互斥量对象

互斥量对象用来确保一个线程独占对一个资源的访问

CreateMutex创建一互斥量对象

OpenMutex   打开一互斥量对象

ReleaseMutex释放互斥量对象所有权

 

A线程创建hMutex之后

 

B线程 
WaitForSingleObject(hMutex, 5000L);     à一旦等待到互斥量信号便拥有了对以下资源的访问权  其他线程就进不来了
//…Code
ReleaseMutex(hMutex)  à释放互斥量对象所有权 让其他线程可以进来

 

Mutex Function

Description

CreateMutex

Creates or opens a named or unnamed mutex object.

OpenMutex

Opens an existing named mutex object.

ReleaseMutex

Releases ownership of the specified mutex object.

 

 

3:临界区

临界区:简述

如果您非常熟悉临界区,并可以不假思索地进行应用,那就可以略过本节。否则,请向下阅读,以对这些内容进行快速回顾。如果您不熟悉这些基础内容,则本节之后的内容就没有太大意义。

临界区是一种轻量级机制,在某一时间内只允许一个线程执行某个给定代码段。通常在修改全局数据(如集合类)时会使用临界区。事件、多用户终端执行程序和信号量也用于多线程同步,但临界区与它们不同,它并不总是执行向内核模式的控制转换,这一转换成本昂贵。稍后将会看到,要获得一个未占用临界区,事实上只需要对内存做出很少的修改,其速度非常快。只有在尝试获得已占用临界区时,它才会跳至内核模式。这一轻量级特性的缺点在于临界区只能用于对同一进程内的线程进行同步。

临界区由 WINNT.H 中所定义的 RTL_CRITICAL_SECTION 结构表示。因为您的 C++ 代码通常声明一个 CRITICAL_SECTION 类型的变量,所以您可能对此并不了解。研究 WINBASE.H 后您会发现:

typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;

我们将在短时间内揭示 RTL_CRITICAL_SECTION 结构的实质。此时,重要问题在于 CRITICAL_SECTION(也称作 RTL_CRITICAL_SECTION)只是一个拥有易访问字段的结构,这些字段可以由 KERNEL32 API 操作。

在将临界区传递给 InitializeCriticalSection 时(或者更准确地说,是在传递其地址时),临界区即开始存在。初始化之后,代码即将临界区传递给 EnterCriticalSection LeaveCriticalSection API。一个线程自 EnterCriticalSection 中返回后,所有其他调用 EnterCriticalSection 的线程都将被阻止,直到第一个线程调用 LeaveCriticalSection 为止。最后,当不再需要该临界区时,一种良好的编码习惯是将其传递给 DeleteCriticalSection

在临界区未被使用的理想情况中,对 EnterCriticalSection 的调用非常快速,因为它只是读取和修改用户模式内存中的内存位置。否则(在后文将会遇到一种例外情况),阻止于临界区的线程有效地完成这一工作,而不需要消耗额外的 CPU 周期。所阻止的线程以内核模式等待,在该临界区的所有者将其释放之前,不能对这些线程进行调度。如果有多个线程被阻止于一个临界区中,当另一线程释放该临界区时,只有一个线程获得该临界区。

 

 

Critical-Section Function

Description

DeleteCriticalSection

Releases all resources used by an unowned critical section object.

EnterCriticalSection

Waits for ownership of the specified critical section object.

InitializeCriticalSection

Initializes a critical section object.

InitializeCriticalSectionAndSpinCount

Initializes a critical section object and sets the spin count for the critical section.

LeaveCriticalSection

Releases ownership of the specified critical section object.

SetCriticalSectionSpinCount

Sets the spin count for the specified critical section.

TryEnterCriticalSection

Attempts to enter a critical section without blocking.

 

 

以上 临界区的优点是速度快 只是读取和修改用户模式内存中的内存位置

事件对象和互斥量要去内核修改信号(在Ring3Ring0之间的转换相当消耗时间) 但是缺点是会造成死锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值