标题：互斥体
互斥体简介
互斥体实现了“互相排斥”（mutual exclusion）同步的简单形式（所以名为互斥体(mutex)）。互斥体禁止多个线程同时进入受保护的代码“临界区”（critical section）。因此，在任意时刻，只有一个线程被允许进入这样的代码保护区。任何线程在进入临界区之前，必须获取（acquire）与此区域相关联的互斥体的所有权。如果已有另一线程拥有了临界区的互斥体，其他线程就不能再进入其中。这些线程必须等待，直到当前的属主线程释放（release）该互斥体。什么时候需要使用互斥体呢？互斥体用于保护共享的易变代码，也就是，全局或静态数据。这样的数据必须通过互斥体进行保护，以防止它们在多个线程同时访问时损坏。
互斥体的创建
在VC中，我们用CreateMutex函数创建互斥体。
HANDLE WINAPI CreateMutex(
__in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,
__in BOOL bInitialOwner,
__in_opt LPCTSTR lpName
);
应用示例
#include <windows.h>
#include <stdio.h>
#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)) 
{ 
// Handle error.
} 
} 
break; 
// The thread got ownership of an abandoned mutex
// The database is in an indeterminate state
case WAIT_ABANDONED: 
return FALSE; 
}
}
return TRUE; 
}
微软MSDN中关于互斥体的备注
The handle returned by CreateMutex has MUTEX_ALL_ACCESS access to the new mutex object and can be used in any function that requires a handle to a mutex object. 
通过CreateMutex 函数返回的句柄拥有MUTEX_ALL_ACCESS 权限，并且可以在任何函数中请求这个互斥体对象句柄。
Any thread of the calling process can specify the mutex-object handle in a call to one of the wait functions.
任何调用进程的线程均可以在WAIT系列的函数中指定这个互斥体对象句柄。
The single-object wait functions return when the state of the specified object is signaled. 
单个对象的等待函数（例如：SignalObjectAndWait, WaitForSingleObject, and WaitForSingleObjectEx ）会在指定对象的状态变为受信状态后返回。
The multiple-object wait functions can be instructed to return either when any one or when all of the specified objects are signaled. When a wait function returns, the waiting thread is released to continue its execution. 
多对象的等待函数将等待任意一个或全部对象都变成受信状态后返回（取决于函数的参数设置）。当等待函数返回，等待线程将继续执行下去。
The state of a mutex object is signaled when it is not owned by any thread. 
当互斥体对象不属于任何一个线程时，互斥体的状态为受信状态。
The creating thread can use the bInitialOwner flag to request immediate ownership of the mutex. 
创建线程可以使用bInitialOwner 标志请求立即获得该互斥体的拥有权。
Otherwise, a thread must use one of the wait functions to request ownership. 
否则，线程必须使用一种等待函数请求拥有权。
When the mutex's state is signaled, one waiting thread is granted ownership, the mutex's state changes to nonsignaled, and the wait function returns. Only one thread can own a mutex at any given time. The owning thread uses the ReleaseMutex function to release its ownership. 
当互斥体对象为受信状态时，假定某个等待线程获得了其拥有权，互斥体状态转为非受信（无信号）状态时，等待函数返回。同一时间只能有一个线程可以拥有某一互斥体。该线程可以使用ReleaseMutex 函数释放拥有权。
The thread that owns a mutex can specify the same mutex in repeated wait function calls without blocking its execution. Typically, you would not wait repeatedly for the same mutex, but this mechanism prevents a thread from deadlocking itself while waiting for a mutex that it already owns. However, to release its ownership, the thread must call ReleaseMutex once for each time that the mutex satisfied a wait. 
一个对某一互斥体拥有所有权的线程可以在重复等待函数中指定已经拥有的那个互斥体（为等待对象），这并不会阻塞线程的执行。典型的例子是，你可能不需要重复等待同一个互斥体（言下之意，你写了重复的等待某一个互斥体对象的代码），这种机制预防了线程在已经拥有了互斥体对象的所有权的时候还要继续等待该互斥体对象时造成的死锁问题。但是，释放所有权时必须调用同样多次数的ReleaseMutex 函数。
Two or more processes can call CreateMutex to create the same named mutex. The first process actually creates the mutex, and subsequent processes open a handle to the existing mutex. 
一个或多个进程可以调用CreateMutex 函数创建一个同名的互斥体，第一个进程真正意义上的创建该互斥体，之后的进程只是打开已经存在的互斥体的句柄。
This enables multiple processes to get handles of the same mutex, while relieving the user of the responsibility of ensuring that the creating process is started first. When using this technique, you should set the bInitialOwner flag to FALSE; otherwise, it can be difficult to be certain which process has initial ownership. 
允许多进程获得同一互斥体的句柄，可以帮助负责任的使用者（使用互斥体的开发人员）确保创建的进程是第一个被运行的进程。（防止游戏多开的方法之一^_^）。使用这种技术你应该设置bInitialOwner 标志为FALSE，否则将很难确定哪个进程有（互斥体的）最初所有权。
Multiple processes can have handles of the same mutex object, enabling use of the object for interprocess synchronization. The following object-sharing mechanisms are available: 多进程可以获得同一互斥体对象的句柄，使得该对象可以用于进程间同步。 A child process created by the CreateProcess function can inherit a handle to a mutex object if the lpMutexAttributes parameter of CreateMutex enabled inheritance. 
如果使用CreateMutex 函数时lpMutexAttributes 参数允许继承，则使用CreateProcess 函数创建的子进程可以继承互斥体对象的句柄。
A process can specify the mutex-object handle in a call to the DuplicateHandle function to create a duplicate handle that can be used by another process. A process can specify the name of a mutex object in a call to the OpenMutex or CreateMutex function. 
进程可以在DuplicateHandle 函数中指定互斥体对象句柄去创建一个复制句柄，以便用于其它进程。进程可以在OpenMutex 函数或CreateMutex 函数中指定互斥体对象的名称。
Use the CloseHandle function to close the handle. The system closes the handle automatically when the process terminates. The mutex object is destroyed when its last handle has been closed. 
使用CloseHandle 函数关闭句柄，系统会在进程销毁时自动关闭句柄，互斥体对象在最后一个句柄被关闭时被销毁。