本文来自: Using Mutex Objects
您可以使用互斥对象来保护共享资源,以防止多个线程或进程同时访问。每个线程在执行访问共享资源的代码之前都必须等待互斥对象的所有权。
以下示例使用 CreateMutex 函数创建互斥对象,并使用 CreateThread 函数创建工作线程。
#include <windows.h>
#include <stdio.h>
#define THREADCOUNT 2
HANDLE ghMutex;
DWORD WINAPI WriteToDatabase( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(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;
}
int main( void )
{
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 1;
}
// 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 1;
}
}
// 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);
return 0;
}
当此进程的线程写入数据库时,它首先使用 WaitForSingleObject 函数请求互斥对象的所有权。如果线程获得互斥对象的所有权,它将写入数据库,然后使用 ReleaseMutex 函数释放其对互斥对象的所有权。
此示例使用结构化异常处理来确保线程正确释放互斥对象。无论 __try 块如何终止,都会执行 __finally 代码块(除非 __try 块包含对 TerminateThread 函数的调用)。这可防止互斥对象被无意放弃。
根据上述案例,我写出了下面的案例:
#include <windows.h>
#include <cstdio>
#include <fstream>
#include <thread>
#include <errhandlingapi.h>
#include <iostream>
using namespace std;
HANDLE ghMutex;
ofstream file;
DWORD WINAPI Operation1(LPVOID lpParam)
{
while (1)
{
DWORD dwWaitResult = WaitForSingleObject(ghMutex,INFINITE);
string content = "I am gay";
file << content << endl;
cout << content << endl;
ReleaseMutex(ghMutex);
}
}
DWORD WINAPI Operation2(LPVOID lpParam)
{
while (1)
{
DWORD dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
string content1 = "I love you";
file << content1 << endl;
cout << content1 << endl;
ReleaseMutex(ghMutex);
}
}
int main()
{
file.open("D:/test.txt");
HANDLE hThread1, hThread2 ;
DWORD threadId1, threadId2 ;
hThread1 = CreateThread(NULL, 0, Operation1, NULL, 0, &threadId1);
hThread2 = CreateThread(NULL, 0, Operation2, NULL, 0, &threadId2);
if ((hThread1 == NULL) || (hThread2 == NULL))
{
cerr << "Failed to create thread." << std::endl;
return 1;
}
ghMutex = CreateMutex(NULL, FALSE, NULL);
// Wait for the thread to finish
DWORD waitResult1 = WaitForSingleObject(hThread1, INFINITE);
DWORD waitResult2 = WaitForSingleObject(hThread2, INFINITE);
if ((waitResult1 == WAIT_FAILED) || (waitResult2 == WAIT_FAILED))
{
cerr << "Failed to wait for thread." << std::endl;
return 1;
}
// Close the thread handle
CloseHandle(hThread1);
CloseHandle(hThread2);
}