使用Mutex对象

http://msdn.microsoft.com/en-us/library/windows/desktop/ms686927(v=vs.85).aspx 

       当多线程或多进程同时访问共享资源时,你可以使用mutex对象保护它们。在可以访问共享资源之前,每个线程必须等待,来获得mutex。例如,如果几个线程访问数据库,线程可以使用mutex对象,使得同时只有一个线程可以写数据库。

      下面的例子,使用CreateMutex函数创建一个mutex对象,使用CreateThread函数创建工作线程。

      当一个线程写数据库时,它先要使用WaitForSingleObject函数请求到mutex的所有权。如果此线程得到了mutex对象的所有权,它便 可以写数据库了,然后用ReleaseMutex函数释放所有权。

      此例使用了结构化异常,确保此线程正确释放mutex对象。_finally中的代码都会执行,无论_try代码块是否正确执行。这样就阻了对mutex对象不当的操作。

      如果mutex被舍弃,拥有此mutex对象的线程不可被正常的释放。在此例吕,共享资深的状态是不确定的,使用mutex对象可以产生难以理解的严重错误。一些程序可以尝试修复共享的资源。此例使用简单的方法,返回错误并停止使用mutex。更多信息,参见Mutex Objects.


#include <windows.h>
#include <stdio.h>

#define THREADCOUNT 2

HANDLE ghMutex; 

DWORD WINAPI WriteToDatabase( LPVOID );

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);

	system("pause");
	return 0;
}

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; 
}
结果

Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...

`Mutex` 是一种用于线程同步的机制,能够帮助程序员保护共享资源(如全局变量),防止多个线程同时访问而导致数据竞争或不可预期的结果。 以下是 `Mutex` 的基本使用步骤: ### 1. 创建 Mutex 首先需要创建一个互斥锁对象,在 C++ 中可以使用 `<mutex>` 库提供的 `std::mutex` 类型。例如: ```cpp #include <mutex> std::mutex mtx; // 定义一个 mutex 对象 ``` ### 2. 加锁 (lock) 当某个线程开始操作共享资源之前,它应该尝试获取该 `Mutex` 锁。如果另一个线程已经持有此锁,则当前线程会阻塞直到释放为止。 ```cpp mtx.lock(); // 获取锁 // 访问共享资源... ``` ### 3. 解锁 (unlock) 完成对共享资源的操作之后一定要记得解锁,以便其他等待中的线程可以获得这个锁并继续执行其任务。 ```cpp mtx.unlock(); // 释放锁 ``` 为了更安全地管理加锁和解锁的过程,推荐配合RAII风格使用的辅助工具——**unique_lock** 或直接采用 try/catch 结构包裹关键部分,并保证无论是否抛出异常都能正常解除锁定状态。 #### 示例代码片段: 下面展示了一个简单的例子说明如何利用 mutex 来确保两个并发运行的任务不会干扰彼此的数据处理过程。 ```cpp #include <iostream> #include <thread> #include <mutex> int shared_data = 0; std::mutex data_mutex; void increment() { for(int i=0;i<1000;++i){ std::lock_guard<std::mutex> guard(data_mutex); // 自动上锁与解锁 ++shared_data; } } int main(){ std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "Final value: " << shared_data << '\n'; } ``` 在这个程序里我们通过引入了 lock_guard 模板类简化手动控制流程的同时也避免忘记调用 unlock 而引发死锁现象的发生几率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值