for(int i=0; i<1000000; i++)
{
lock.Lock();
lock.Unlock();
}
long end = GetTickCount();
printf("Stop Mutex Test from %ld\n", end);
测试数据:用GetTickCount()得到:
Start Mutex Test from 14650984
Stop Mutex Test from 14655343
Start CriticalSection Test from 14655343
Stop CriticalSection Test from 14655359
Start Semaphore Test from 14655359
Stop Semaphore Test from 14659671
结论:window平台下:Semaphore
和Mutex性能差不多,但是CriticalSection性能最好(不到100ms),而且数量级都不一样(其他都在4s以上,而且高占用cpu)。
对于linux下和solaris的比较,请大家给出相应的数据。(好像没有CriticalSection)
如果测试方式不当,也请大家提出!
线程的同步机制:
1、 Event
用事件(Event)来同步线程是最具弹性的了。一个事件有两种状态:激发状态和未激发状态。也称有信号状态和无信号状态。事件又分两种类型:手动重置事件和自动重置事件。手动重置事件被设置为激发状态后,会唤醒所有等待的线程,而且一直保持为激发状态,直到程序重新把它设置为未激发状态。自动重置事件被设置为激发状态后,会唤醒“一个”等待中的线程,然后自动恢复为未激发状态。所以用自动重置事件来同步两个线程比较理想。MFC中对应的类为CEvent.。CEvent的构造函数默认创建一个自动重置的事件,而且处于未激发状态。共有三个函数来改变事件的状态:SetEvent,ResetEvent和PulseEvent。用事件来同步线程是一种比较理想的做法,但在实际的使用过程中要注意的是,对自动重置事件调用SetEvent和PulseEvent有可能会引起死锁,必须小心。
2、 Critical Section
使用临界区域的第一个忠告就是不要长时间锁住一份资源。这里的长时间是相对的,视不同程序而定。对一些控制软件来说,可能是数毫秒,但是对另外一些程序来说,可以长达数分钟。但进入临界区后必须尽快地离开,释放资源。如果不释放的话,会如何?答案是不会怎样。如果是主线程(GUI线程)要进入一个没有被释放的临界区,呵呵,程序就会挂了!临界区域的一个缺点就是:Critical
Section不是一个核心对象,无法获知进入临界区的线程是生是死,如果进入临界区的线程挂了,没有释放临界资源,系统无法获知,而且没有办法释放该临界资源。这个缺点在互斥器(Mutex)中得到了弥补。Critical
Section在MFC中的相应实现类是CcriticalSection。CcriticalSection::Lock()进入临界区,CcriticalSection::UnLock()离开临界区。
3、 Mutex
互斥器的功能和临界区域很相似。区别是:Mutex所花费的时间比Critical
Section多的多,但是Mutex是核心对象(Event、Semaphore也是),可以跨进程使用,而且等待一个被锁住的Mutex可以设定TIMEOUT,不会像Critical
Section那样无法得知临界区域的情况,而一直死等。MFC中的对应类为CMutex。Win32函数有:创建互斥体CreateMutex()
,打开互斥体OpenMutex(),释放互斥体ReleaseMutex()。Mutex的拥有权并非属于那个产生它的线程,而是最后那个对此Mutex进行等待操作(WaitForSingleObject等等)并且尚未进行ReleaseMutex()操作的线程。线程拥有Mutex就好像进入Critical
Section一样,一次只能有一个线程拥有该Mutex。如果一个拥有Mutex的线程在返回之前没有调用ReleaseMutex(),那么这个Mutex就被舍弃了,但是当其他线程等待(WaitForSingleObject等)这个Mutex时,仍能返回,并得到一个WAIT_ABANDONED_0返回值。能够知道一个Mutex被舍弃是Mutex特有的。
4、 Semaphore
信号量是最具历史的同步机制。信号量是解决producer/consumer问题的关键要素。对应的MFC类是Csemaphore。Win32函数CreateSemaphore()用来产生信号量。ReleaseSemaphore()用来解除锁定。Semaphore的现值代表的意义是目前可用的资源数,如果Semaphore的现值为1,表示还有一个锁定动作可以成功。如果现值为5,就表示还有五个锁定动作可以成功。当调用Wait…等函数要求锁定,如果Semaphore现值不为0,Wait…马上返回,资源数减1。当调用ReleaseSemaphore()资源数加1,当时不会超过初始设定的资源总数。
CRITICALSECTION是OS在用户态实现的同步,而其它的是OS在内核态下实现的同步,后者的访问显然要更费CPU周期,后者有个好处就是能在多进程间进行线程同步,前者则不行
EVENT,MUTE,SEMAPHORE均为内核对象,在全局系统中只能存在由命名确实的唯一对象,通过这个命名,它们均可以在进程间共享同一个对象,因此它们在进程间进行线程同步.
Solaris下各个同步对象的基本用法和WINDOWS差异不大。
但在嵌套LOCK方面有差异,好像Windows在嵌套LOCK时会挂住(记不太清楚是Windows还是Solaris)。
> From: can...@gmail.com
> To: ACE...@googlegroups.com
> Subject: Re: windows下mutex、Semaphore和CriticalSection用作锁时的性能对比!
> Date: Mon, 27 Feb 2006 12:23:12 +0000
>
> 怎么没有人说说linux或solaris下的情况?