所以也就不难理解为什么临界区不能跨进程使用
可以看一下临界区的定义
typedef struct _RTL_CRITICAL_SECTION {
PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
//
// The following three fields control entering and exiting the critical
// section for the resource
//
LONG LockCount;
LONG RecursionCount;
HANDLE OwningThread; // from the thread's ClientId->UniqueThread
HANDLE LockSemaphore;
ULONG_PTR SpinCount; // force size on 64-bit systems when packed
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
typedef struct _KEVENT {
DISPATCHER_HEADER Header;
} KEVENT, *PKEVENT, *PRKEVENT;
typedef struct _KMUTANT {
DISPATCHER_HEADER Header;
LIST_ENTRY MutantListEntry;
struct _KTHREAD *OwnerThread;
BOOLEAN Abandoned;
UCHAR ApcDisable;
} KMUTANT, *PKMUTANT, *PRKMUTANT, KMUTEX, *PKMUTEX, *PRKMUTEX;
mutex 是event的超集
mutex比event多了一个ownerthread,当调用releasemutex时,如果mutex的ownerthread不是你调用的线程,会失败
而event不存在此问题
mutext更多的是用在对同一个资源访问互斥上,
而event更多用于线程同步,
另外event可以设置是否是手动设置恢复信号,这个mutex是做不到的,也就是说如果event是手动的,setevent可以令等待它的N个线程激活
但是mutext只能同一时刻允许一个线程获得使用权.不可能用mutex做到,让等待它的多个线程同时解锁.
如果只有两个线程的话,我觉得两者的差别就没有那么大了.
贴上msdn的两个例子就可以更清楚的看到两者之间的差别
第二个例子中的mutex完全可以用event代替.
#include
#include
#define THREADCOUNT 4
HANDLE ghGlobalWriteEvent;
HANDLE ghReadEvents[THREADCOUNT];
DWORD WINAPI ThreadProc(LPVOID);
void CreateEventsAndThreads(void)
{
HANDLE hThread;
DWORD i, dwThreadID;
// Create a manual-reset event object. The master thread sets
// this to nonsignaled when it writes to the shared buffer.
ghGlobalWriteEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
TRUE, // initial state is signaled
TEXT("WriteEvent") // object name
);
if (ghGlobalWriteEvent == NULL)
{
printf("CreateEvent failed (%d)\n", GetLastError());
return;
}
else if ( GetLastError() == ERROR_ALREADY_EXISTS )
{
printf("Named event already exists.\n");
return;
}
// Create multiple threads and an auto-reset event object
// for each thread. Each thread sets its event object to
// signaled when it is not reading from the shared buffer.
for(i = 0; i < THREADCOUNT; i++)
{
// Create the auto-reset event
ghReadEvents[i] = CreateEvent(
NULL, // no security attributes
FALSE, // auto-reset event
TRUE, // initial state is signaled
NULL); // object not named
if (ghReadEvents[i] == NULL)
{
printf("CreateEvent failed (%d)\n", GetLastError());
return;
}
hThread = CreateThread(NULL,
0,
ThreadProc,
&ghReadEvents[i], // pass event handle
0,
&dwThreadID);
if (hThread == NULL)
{
printf("CreateThread failed (%d)\n", GetLastError());
return;
}
}
}
void WriteToBuffer(VOID)
{
DWORD dwWaitResult, i;
// Reset ghGlobalWriteEvent to nonsignaled, to block readers
if (! ResetEvent(ghGlobalWriteEvent) )
{
printf("ResetEvent failed (%d)\n", GetLastError());
return;
}
// Wait for all reading threads to finish reading
dwWaitResult = WaitForMultipleObjects(
THREADCOUNT, // number of handles in array
ghReadEvents, // array of read-event handles
TRUE, // wait until all are signaled
INFINITE); // indefinite wait
switch (dwWaitResult)
{
// All read-event objects were signaled
case WAIT_OBJECT_0:
// TODO: Write to the shared buffer
printf("Main thread writing to the shared buffer...\n");
break;
// An error occurred
default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}
// Set ghGlobalWriteEvent to signaled
if (! SetEvent(ghGlobalWriteEvent) )
{
printf("SetEvent failed (%d)\n", GetLastError());
ExitProcess(0);
}
// Set all read events to signaled
for(i = 0; i < THREADCOUNT; i++)
if (! SetEvent(ghReadEvents[i]) )
{
printf("SetEvent failed (%d)\n", GetLastError());
return;
}
}
void CloseEvents()
{
int i;
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(ghReadEvents[i]);
CloseHandle(ghGlobalWriteEvent);
}
void main()
{
int i;
// TODO: Create the shared buffer
// Create the events and THREADCOUNT threads to read from the buffer
CreateEventsAndThreads();
// Write to the buffer three times, just for test purposes
for(i=0; i < 3; i++)
WriteToBuffer();
// Close the events
CloseEvents();
}
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
DWORD dwWaitResult;
HANDLE hEvents[2];
hEvents[0] = *(HANDLE*)lpParam; // thread's read event
hEvents[1] = ghGlobalWriteEvent; // global write event
dwWaitResult = WaitForMultipleObjects(
2, // number of handles in array
hEvents, // array of event handles
TRUE, // wait till all are signaled
INFINITE); // indefinite wait
switch (dwWaitResult)
{
// Both event objects were signaled
case WAIT_OBJECT_0:
// TODO: Read from the shared buffer
printf("Thread %d reading from buffer...\n",
GetCurrentThreadId());
break;
// An error occurred
default:
printf("Wait error: %d\n", GetLastError());
ExitThread(0);
}
// Set the read event to signaled
if (! SetEvent(hEvents[0]) )
{
printf("SetEvent failed (%d)\n", GetLastError());
ExitThread(0);
}
return 1;
}
这个是event的
#include
#include
#define THREADCOUNT 2
HANDLE ghMutex;
DWORD WINAPI WriteToDatabase( LPVOID );
void main()
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
// Create a mutex with no initial owner
ghMutex = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (ghMutex == NULL)
{
printf("CreateMutex error: %d\n", GetLastError());
return;
}
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) WriteToDatabase,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return;
}
}
// Wait for all threads to terminate
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread and mutex handles
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghMutex);
}
DWORD WINAPI WriteToDatabase( LPVOID lpParam )
{
DWORD dwCount=0, dwWaitResult;
// Request ownership of mutex.
while( dwCount < 20 )
{
dwWaitResult = WaitForSingleObject(
ghMutex, // handle to mutex
INFINITE); // no time-out interval
switch (dwWaitResult)
{
// The thread got ownership of the mutex
case WAIT_OBJECT_0:
__try {
// TODO: Write to the database
printf("Thread %d writing to database...\n",
GetCurrentThreadId());
dwCount++;
}
__finally {
// Release ownership of the mutex object
if (! ReleaseMutex(ghMutex))
{
// Deal with error.
}
}
break;
// The thread got ownership of an abandoned mutex
case WAIT_ABANDONED:
return FALSE;
}
}
return TRUE;
}