我写了一个小程序来比较Windows中Critical Section和Mutex的性能。
在我运行的测试中,获取临界区似乎更慢:O谁能解释为什么这两件事需要几乎相同的时间,以及内部发生了什么。
这是我使用的计时器- http://cplus.about.com/od/howtodothingsi2/a/timing.htm
#include "stdafx.h"
#include<iostream>
#include<vector>
#include "h_timer.h"
#include<WinBase.h>
#include<Windows.h>
#include<stdio.h>
#define MAX_THREADS 2000
//Comment and Uncomment this to enable/disable critialSection / Mutex
#define CRIT 1
using namespace std;
HANDLE Mutex;
CRITICAL_SECTION critSection;
DWORD WINAPI Contention( LPVOID );
int main( void )
{
HANDLE Thread[MAX_THREADS];
DWORD ThreadID;
int i;
#ifdef CRIT
//create a critical section
InitializeCriticalSection(&critSection);
#else
// Create a mutex with no initial owner
Mutex = CreateMutex( NULL, FALSE,NULL);
#endif
// Create worker threads
CStopWatch timer, tempTimer;
timer.startTimer();
for( i=0; i < MAX_THREADS; i++ )
{
Thread[i] = CreateThread( NULL,
0,(LPTHREAD_START_ROUTINE)Contention,NULL,0,&ThreadID);
}
WaitForMultipleObjects(MAX_THREADS, Thread, TRUE, INFINITE);
timer.stopTimer();
cout<<endl<<"Elapsed Time:"<<timer.getElapsedTime();
cin.get();
// Close thread and mutex handles
for( i=0; i < MAX_THREADS; i++ )
CloseHandle(Thread[i]);
CloseHandle(Mutex);
return 0;
}
DWORD WINAPI Contention( LPVOID lpParam )
{
#ifdef CRIT
EnterCriticalSection(&critSection);
//printf("ThreadId: %d\n",GetCurrentThreadId());
//printf("Let's try Again. %d\n\n", GetCurrentThreadId());
LeaveCriticalSection(&critSection);
#else
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwCount=0, dwWaitResult;
// Request ownership of mutex.
dwWaitResult = WaitForSingleObject(
ghMutex, // handle to mutex
INFINITE); // no time-out interval
dwCount++;
ReleaseMutex(ghMutex);
#endif
return TRUE;
}对于2000个线程,在四核HPZ210上,两者都需要大约1.5秒。
发布于 2012-07-04 09:49:16
我认为有两个因素:
主要是--你的程序主要是由线程创建开销决定的。您正在创建和销毁2000个线程,并且每个线程只访问一次mutex/CS。创建线程所花费的时间淹没了锁定/解锁时间的差异。
此外,您可能没有测试针对这些锁进行优化的用例。尝试生成两个线程,每个线程都尝试访问互斥锁/CS数千次。
发布于 2012-07-04 09:57:31
临界区是用户模式和内核模式的混合体。它们试图在退回到更昂贵的信号量(内核模式)之前,通过使用自旋锁(用户模式)来阻止线程的上下文切换。这提高了真实场景中的性能。相反,互斥锁是纯粹的内核模式,它会立即等待,执行上下文切换。
通过在2000个线程之间进行100%的争用,您几乎可以肯定临界区将尽可能多地旋转,吞噬CPU,最后执行互斥锁所做的事情,并在内核模式下执行等待。因此,对于他们来说,在这种情况下放慢速度是有意义的。
还有贾普瑞斯说的话。线程创建非常慢。
https://stackoverflow.com/questions/11321417
复制相似问题