注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

写着玩

Bob

 
 
 

日志

 
 
 
 

线程学习 (4) 线程的同步--1  

2009-08-25 00:24:08|  分类: Win32 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

对于多线程编程来说,最难得有两点:1. 线程的生命周期的管理;2. 线程同步。在前面几节中我们讨论了第一个问题,现在我们来讨论第二个问题。到目前为止,我们创建线程都是相互独立的。线程之间没有任何瓜葛。因此他们都运行得很好。没有任何问题。性能也很高。这一切看起来都非常的美好。比起单线程来说简直好得太多了。然而不幸的是在多线程编程中,多个线程都是相互独立的事情太少了。更多的是虽然一个线程处理一些事情,另一个线程处理另外一些事情,但是其中一些线程需要了解其他线程的处理结果或者需要在其处理完成之后才能进行。最简单的情况比如:一个线程通过计算,将计算的结果写入一个全局变量,另外一个线程则读取全局变量进行显示。如果不采取任何同步措施,那么就无法保证读数据的线程读到的数据时写数据线程写入之后的结果。为了让线程了解其他线程结束之后的结果或者需要访问相同的资源并改变资源从而使得同一进程中的多个线程协调的工作就叫线程的同步。因此也就有两种基本情况是需要使用线程同步的:1. 当多个线程会访问同一个资源并且会改变资源;2. 一个线程需要了解其他一个或多个线程何时结束(或者说是需要通知其他线程);打个比方说也就是“兄弟,这东西我且用着那,您得等会。”“大哥,我活干完啦,你上吧。”也就这么个意味。

       要使用好多线程,线程同步是一定要过关的。线程同步是一个不小的话题,从大方面来说可以分为两大类,一类是用户模式同步对象,一类是内核模式同步对象。前面章节我们说过,使用内核对象是需要从用户态转入内核态的,而这个切换是非常花费时间的,大约是1000个时钟周期。所以用户模式的同步对象最大的特点是效率高。但是也有缺点:不能跨进程。而内核模式同步对象大概正好相反。内核对象可是系统级的东东,所谓钱多好办事,自然功能也就强多了。
 用户模式同步对象包括原子访问和临界区;内核模式同步对象包括事件,等待定时器,信号量,互斥量。下面我们来学习每个对象的具体用法。

       1. 原子访问
        一直都不是很理解为啥叫原子访问。ATOM(阿童木),也许和那个认为原子是最小物质的年代的理论有关吧。
既然是最小的物质了,自然是不可以再分了。所以可以理解为原子访问就是不可以再分割的操作。也就是不会被其他更高优先级中断抢先得操作。说得通俗点就是系统能保证这个操作是一次性搞定的,中途绝不能休息。互锁函数的家族十分的庞大,可以查看msdn(http://msdn.microsoft.com/en-us/library/ms683597(VS.85).aspx)以InterLocked开始的函数都是户数函数。使用互锁函数的优点是:他的速度要比其他的CriticalSection,Mutex,Event,Semaphore快很多。通常少于50个时钟周期

一般的互锁函数:

Interlocked function Description
InterlockedAdd Performs an atomic addition operation on the specified LONG values.
InterlockedAdd64 Performs an atomic addition operation on the specified LONGLONG values.
InterlockedAddAcquire Performs an atomic addition operation on the specified LONG values. The operation is performed with acquire memory access semantics.
InterlockedAddAcquire64 Performs an atomic addition operation on the specified LONGLONG values. The operation is performed with acquire memory access semantics.
InterlockedAddRelease Performs an atomic addition operation on the specified LONG values. The operation is performed with release memory access semantics.
InterlockedAddRelease64 Performs an atomic addition operation on the specified LONGLONG values. The operation is performed with release memory access semantics.
InterlockedAnd Performs an atomic AND operation on the specified LONG values.
InterlockedAndAcquire Performs an atomic AND operation on the specified LONG values. The operation is performed with acquire memory access semantics.
InterlockedAndRelease Performs an atomic AND operation on the specified LONG values. The operation is performed with release memory access semantics.
InterlockedAnd8 Performs an atomic AND operation on the specified char values.
InterlockedAnd8Acquire Performs an atomic AND operation on the specified char values. The operation is performed with acquire memory access semantics.
InterlockedAnd8Release Performs an atomic AND operation on the specified char values. The operation is performed with release memory access semantics.
InterlockedAnd16 Performs an atomic AND operation on the specified SHORT values.
InterlockedAnd16Acquire Performs an atomic AND operation on the specified SHORT values. The operation is performed with acquire memory access semantics.
InterlockedAnd16Release Performs an atomic AND operation on the specified SHORT values. The operation is performed with release memory access semantics.
InterlockedAnd64 Performs an atomic AND operation on the specified LONGLONG values.
InterlockedAnd64Acquire Performs an atomic AND operation on the specified LONGLONG values. The operation is performed with acquire memory access semantics.
InterlockedAnd64Release Performs an atomic AND operation on the specified LONGLONG values. The operation is performed with release memory access semantics.
InterlockedBitTestAndReset Tests the specified bit of the specified LONG value and sets it to 0.
InterlockedBitTestAndReset64 Tests the specified bit of the specified LONG64 value and sets it to 0.
InterlockedBitTestAndSet Tests the specified bit of the specified LONG value and sets it to 1.
InterlockedBitTestAndSet64 Tests the specified bit of the specified LONG64 value and sets it to 1.
InterlockedCompare64Exchange128 Performs an atomic compare-and-exchange operation on the specified values. The function compares the specified 64-bit values and exchanges with the specified 128-bit value based on the outcome of the comparison.
InterlockedCompare64ExchangeAcquire128 Performs an atomic compare-and-exchange operation on the specified values. The function compares the specified 64-bit values and exchanges with the specified 128-bit value based on the outcome of the comparison. The operation is performed with acquire memory access semantics.
InterlockedCompare64ExchangeRelease128 Performs an atomic compare-and-exchange operation on the specified values. The function compares the specified 64-bit values and exchanges with the specified 128-bit value based on the outcome of the comparison. The operation is performed with release memory access semantics.
InterlockedCompareExchange Performs an atomic compare-and-exchange operation on the specified values. The function compares two specified 32-bit values and exchanges with another 32-bit value based on the outcome of the comparison.
InterlockedCompareExchange64 Performs an atomic compare-and-exchange operation on the specified values. The function compares two specified 64-bit values and exchanges with another 64-bit value based on the outcome of the comparison.
InterlockedCompareExchangeAcquire Performs an atomic compare-and-exchange operation on the specified values. The function compares two specified 32-bit values and exchanges with another 32-bit value based on the outcome of the comparison. The operation is performed with acquire memory access semantics.
InterlockedCompareExchangeAcquire64 Performs an atomic compare-and-exchange operation on the specified values. The function compares two specified 64-bit values and exchanges with another 64-bit value based on the outcome of the comparison. The exchange is performed with acquire memory access semantics.
InterlockedCompareExchangePointer Performs an atomic compare-and-exchange operation on the specified pointer values. The function compares two specified pointer values and exchanges with another pointer value based on the outcome of the comparison.
InterlockedCompareExchangePointerAcquire Performs an atomic compare-and-exchange operation on the specified pointer values. The function compares two specified pointer values and exchanges with another pointer value based on the outcome of the comparison. The operation is performed with acquire memory access semantics.
InterlockedCompareExchangePointerRelease Performs an atomic compare-and-exchange operation on the specified pointer values. The function compares two specified pointer values and exchanges with another pointer value based on the outcome of the comparison. The operation is performed with release memory access semantics.
InterlockedCompareExchangeRelease Performs an atomic compare-and-exchange operation on the specified values. The function compares two specified 32-bit values and exchanges with another 32-bit value based on the outcome of the comparison. The exchange is performed with release memory access semantics.
InterlockedCompareExchangeRelease64 Performs an atomic compare-and-exchange operation on the specified values. The function compares two specified 64-bit values and exchanges with another 64-bit value based on the outcome of the comparison. The exchange is performed with release memory access semantics.
InterlockedDecrement Decrements (decreases by one) the value of the specified 32-bit variable as an atomic operation.
InterlockedDecrement64 Decrements (decreases by one) the value of the specified 64-bit variable as an atomic operation.
InterlockedDecrementAcquire Decrements (decreases by one) the value of the specified 32-bit variable as an atomic operation. The operation is performed with acquire memory access semantics.
InterlockedDecrementAcquire64 Decrements (decreases by one) the value of the specified 64-bit variable as an atomic operation. The operation is performed with acquire memory access semantics.
InterlockedDecrementRelease Decrements (decreases by one) the value of the specified 32-bit variable as an atomic operation. The operation is performed with release memory access semantics.
InterlockedDecrementRelease64 Decrements (decreases by one) the value of the specified 64-bit variable as an atomic operation. The operation is performed with release memory access semantics.
InterlockedExchange Sets a 32-bit variable to the specified value as an atomic operation.
InterlockedExchange64 Sets a 64-bit variable to the specified value as an atomic operation.
InterlockedExchangeAcquire Sets a 32-bit variable to the specified value as an atomic operation. The operation is performed with acquire memory access semantics.
InterlockedExchangeAcquire64 Sets a 32-bit variable to the specified value as an atomic operation. The operation is performed with acquire memory access semantics.
InterlockedExchangeAdd Performs an atomic addition of two 32-bit values.
InterlockedExchangeAdd64 Performs an atomic addition of two 64-bit values.
InterlockedExchangeAddAcquire Performs an atomic addition of two 32-bit values. The operation is performed with acquire memory access semantics.
InterlockedExchangeAddAcquire64 Performs an atomic addition of two 64-bit values. The operation is performed with acquire memory access semantics.
InterlockedExchangeAddRelease Performs an atomic addition of two 32-bit values. The operation is performed with release memory access semantics.
InterlockedExchangeAddRelease64 Performs an atomic addition of two 64-bit values. The operation is performed with release memory access semantics.
InterlockedExchangePointer Atomically exchanges a pair of pointer values.
InterlockedExchangePointerAcquire Atomically exchanges a pair of pointer values. The operation is performed with acquire memory access semantics.
InterlockedIncrement Increments (increases by one) the value of the specified 32-bit variable as an atomic operation.
InterlockedIncrement64 Increments (increases by one) the value of the specified 64-bit variable as an atomic operation.
InterlockedIncrementAcquire Increments (increases by one) the value of the specified 32-bit variable as an atomic operation. The operation is performed using acquire memory access semantics.
InterlockedIncrementAcquire64 Increments (increases by one) the value of the specified 64-bit variable as an atomic operation. The operation is performed using acquire memory access semantics.
InterlockedIncrementRelease Increments (increases by one) the value of the specified 32-bit variable as an atomic operation. The operation is performed using release memory access semantics.
InterlockedIncrementRelease64 Increments (increases by one) the value of the specified 64-bit variable as an atomic operation. The operation is performed using release memory access semantics.
InterlockedOr Performs an atomic OR operation on the specified LONG values.
InterlockedOrAcquire Performs an atomic OR operation on the specified LONG values. The operation is performed with acquire memory access semantics.
InterlockedOrRelease Performs an atomic OR operation on the specified LONG values. The operation is performed with release memory access semantics.
InterlockedOr8 Performs an atomic OR operation on the specified char values.
InterlockedOr8Acquire Performs an atomic OR operation on the specified char values. The operation is performed with acquire memory access semantics.
InterlockedOr8Release Performs an atomic OR operation on the specified char values. The operation is performed with release memory access semantics.
InterlockedOr16 Performs an atomic OR operation on the specified SHORT values.
InterlockedOr16Acquire Performs an atomic OR operation on the specified SHORT values. The operation is performed with acquire memory access semantics.
InterlockedOr16Release Performs an atomic OR operation on the specified SHORT values. The operation is performed with release memory access semantics.
InterlockedOr64 Performs an atomic OR operation on the specified LONGLONG values.
InterlockedOr64Acquire Performs an atomic OR operation on the specified LONGLONG values. The operation is performed with acquire memory access semantics.
InterlockedOr64Release Performs an atomic OR operation on the specified LONGLONG values. The operation is performed with release memory access semantics.
InterlockedXor Performs an atomic XOR operation on the specified LONG values.
InterlockedXorAcquire Performs an atomic XOR operation on the specified LONG values. The operation is performed with acquire memory access semantics.
InterlockedXorRelease Performs an atomic XOR operation on the specified LONG values. The operation is performed with release memory access semantics.
InterlockedXor8 Performs an atomic XOR operation on the specified char values.
InterlockedXor8Acquire Performs an atomic XOR operation on the specified char values. The operation is performed with acquire memory access semantics.
InterlockedXor8Release Performs an atomic XOR operation on the specified char values. The operation is performed with release memory access semantics.
InterlockedXor16 Performs an atomic XOR operation on the specified SHORT values.
InterlockedXor16Acquire Performs an atomic XOR operation on the specified SHORT values. The operation is performed with acquire memory access semantics.
InterlockedXor16Release Performs an atomic XOR operation on the specified SHORT values. The operation is performed with release memory access semantics.
InterlockedXor64 Performs an atomic XOR operation on the specified LONGLONG values.
InterlockedXor64Acquire Performs an atomic XOR operation on the specified LONGLONG values. The operation is performed with acquire memory access semantics.
InterlockedXor64Release Performs an atomic XOR operation on the specified LONGLONG values. The operation is performed with release memory access semantics.

链表的互锁函数:

Singly-linked list function Description
InitializeSListHead Initializes the head of a singly linked list.
InterlockedFlushSList Flushes the entire list of items in a singly linked list.
InterlockedPopEntrySList Removes an item from the front of a singly linked list.
InterlockedPushEntrySList Inserts an item at the front of a singly linked list.
QueryDepthSList Retrieves the number of entries in the specified singly linked list.
RtlFirstEntrySList Retrieves the first entry in a singly linked list.
RtlInitializeSListHead Initializes the head of a singly linked list. Applications should call InitializeSListHead instead.
RtlInterlockedFlushSList Flushes the entire list of items in a singly linked list. Applications should call InterlockedFlushSList instead.
RtlInterlockedPopEntrySList Removes an item from the front of a singly linked list. Applications should call InterlockedPopEntrySList instead.
RtlInterlockedPushEntrySList Inserts an item at the front of a singly linked list. Applications should call InterlockedPushEntrySList instead.
RtlQueryDepthSList Retrieves the number of entries in the specified singly linked list. Applications should call QueryDepthSList instead.

具体用法可以查看MSDN。在众多的原子操作函数中,最常见的有以下几个:
InterlockedExhangeAdd,InterlockedExchange,InterlockedCompareExchange,InterlockedIncrement和InterlockedDecrement。最后两个在COM中应该很熟悉。

2. 临界区
临界区是指一小段代码,在执行前必须独占对某些资源的访问权。也就是以原子操作的方式来访问资源。换句话说就是你用了别人就没法用了。要用怎么办?等呗。等多久?先占得人说了算!中国有句古话叫“占着茅坑不拉屎”。在这里用太合适了。茅坑就是我们说的资源,想用茅坑的人就是线程啦。一个家伙进去了,同时把牌牌给翻成红色,这时候再有人要进去就得等了。只有里面那个家伙出来并且把牌牌翻成绿色的才能进去。所以用临界区得非常小心才行。如果出来那家伙人走了,可是忘记把牌牌翻成绿色的话,虽然人走了,不过坑就算是废啦。可是可是你还在傻傻的等。如果有个家伙进去了,可是忘记把牌牌翻成红色的,这时你到了门口一看是绿牌牌自然就进去了。。。oh,My God!所以各位千万记得使用临界区时一定记得进去出来都得“翻牌牌”。切记切记!
          临界区是用户态的同步对象,因此只能在进程内使用,他无法跨进程。在使用的过程中也无法移动或拷贝或修改。对于线程的获取顺序没有定义,因此不能假定哪个线程将会首先获得临界区。使用完临界区必须执行删除操作。而且一个临界区是不允许进行重复初始化的。否则将产生不可预料的结果。
       临界区的使用也很简单,主要有四个函数:

   void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);初始化临界区。这个函数虽然没有返回值,但是在低内存时会抛出STATUS_NO_MEMORY 的异常.

线程学习 (4) 线程的同步--1 - yolcy - 写着玩void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);进入临界区,也就是把牌牌翻成红色的。其他人就进不来啦。如果这个时候本来牌牌就是红色的话,那么就会一直等待,直到天荒地老。也许你会问:天荒地老是多老?其实也不是很久。临界区其实是有timeout的,大约30天的样子吧。这个值是在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CriticalSectionTimeout设定的。如果你真的等待天荒地老的那一天,那么你将收到一个EXCEPTION_POSSIBLE_DEADLOCK 得异常(通常不需要处理)。

线程学习 (4) 线程的同步--1 - yolcy - 写着玩void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);退出临界区,也就是把牌牌翻成绿色的,告诉其他人可以使用了。如果你忘记调用这个函数,那么其他线程就真的等到天荒地老了。

线程学习 (4) 线程的同步--1 - yolcy - 写着玩void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);删除临界区。如果一个线程拥有的临界区被删除了,那么等待的状态是不确定的。如果线程删除了,那么他拥有的临界区的状态也是不确定的。因此在删除线程和临界区时得特别小心。

使用临界区需要注意:

1.不允许临界区内的操作过长,因为这样可能造成其他线程长时间等待。
       2.临界区不能跨进程使用

  评论这张
 
阅读(819)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017