本文共 3293 字,大约阅读时间需要 10 分钟。
当两个或更多线程需要同时访问一个共享资源时,为了保证程序的正常运行,需要保证同一个资源在同一时刻只能有一个线程去访问它。Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。
互斥量与关键段(线程同步方式)的行为完全相同,当互斥量是内核对象,而关键段是用户模式下的的同步对象。互斥量对象包含: 一个线程 ID ,使用计数和递归计数 。线程 ID 表示当前占用该互斥量的线程 ID ,递归计数表示该线程占用互斥量的次数,使用计数表示使用互斥量对象的不同线程的个数。
互斥量对象有许多用途,它是使用最为频繁的内核对象之一,一般用来对多个进程访问同一块内存进行同步。
HANDLE WINAPI CreateMutex( _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, _In_ BOOL bInitialOwner, _In_opt_ LPCTSTR lpName);
参数说明
lpMutexAttributes:互斥量安全访问属性,一般置为 NULL ; bInitialOwner:控制互斥量的初始状态,一般设置为 false ,是互斥量的线程 ID 和递归计数都设为 0 ,表示互斥量不被任何进程占用,处于触发状态,其他进程可以进行调用等待函数,获得该互斥量对象,获得对同步资源的占用。如果初始值设为 true ,互斥量的线程 ID 设置为当前线程,递归计数设为 1 ,表示当前线程占用互斥量对象,拥有对同步资源的独占,互斥量处于未触发状态。 lpName:用于创建有名的内核对象,即用来创建跨进程边界的内核对象。
CreateMutex 用于创建名为 lpName 的互斥量内核对象,并返回指向该内核对象的句柄。如果该内核对象已经存在,那么 CreateMutex 会返回该内核对象的句柄,并通过系统返回错误 ERROR_ALREADY_EXISTS ,通过 GetLastError ()获得。
HANDLE WINAPI OpenMutex( _In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ LPCTSTR lpName);
参数说明
dwDesiredAccess:对互斥量对象访问权限的设置, MUTEX_ALL_ACCESS 请求对互斥体的完全访问, MUTEX_MODIFY_STATE 允许使用 ReleaseMutex 函数, SYNCHRONIZE 允许互斥体对象同步使用; bInheritHandle:是否希望子进程继承互斥量对象的句柄,一般设置为false ; lpName:要打开的互斥量对象的名称;
OpenMutex 用于打开已经存在的互斥量对象,若打开成功,则返回指向该内核对象的句柄,否则返回 NULL 。可以使用 CreateMutex 来实现打开功能。
DWORD WINAPI WaitForSingleObject( _In_ HANDLE hHandle, _In_ DWORD dwMilliseconds);
参数说明
hHandle :指向内核对象的句柄; dwMilliseconds:线程最大等待多长时间,直到该对象被触发。经常使用INFINITE ,表示阻塞等待。
WaitForSingleObject被称呼为等待函数,是等待内核对象被触发通用的等待函数,被用在所有的内核对象触发等待中。等待函数在等待互斥量内核对象时,会进行互斥量的线程ID 是否为 0 ,如果为非 0 ,表示互斥量处于未触发状态,等待函数会被阻塞。当另外一个线程将互斥量释放,使其线程 ID 为 0 时,系统会唤醒阻塞的等待函数,把互斥量的线程 ID 设置为它的线程 ID ,使其成为可调度状态 。 还有一个WaitForMultipleObject函数,用于等待多个内核对象被触发。
BOOL WINAPI ReleaseMutex( _In_ HANDLE hMutex);
参数说明
hMutex:互斥量内核对象的句柄;当一个线程访问完通过互斥量对象获得的独占资源后,应该调用ReleaseMutex,使互斥量恢复为未触发状态。即设置互斥量对象的线程ID 和递归计数为 0 ,当递归计数大于 1 时,还有进行对应多次的 ReleaseMutex 。
DWORD WINAPI my_thread1(LPVOID m_pParameter); //用户线程1DWORD WINAPI my_thread2(LPVOID m_pParameter); //用户线程2UINT count = 0; //全局的计数函数HANDLE m_hMutex; //定义一个互斥量句柄int _tmain(int argc, _TCHAR* argv[]){ system("color f0"); int count_size(50); m_hMutex = ::CreateMutex(NULL, false, NULL); //初始化互斥量 HANDLE m_h1 = CreateThread(NULL, NULL, my_thread1, &count_size, NULL, NULL); //用户线程1 HANDLE m_h2 = CreateThread(NULL, NULL, my_thread2, &count_size, NULL, NULL); //用户线程2 ::WaitForSingleObject(m_h1, INFINITE); //等待子线程结束 ::WaitForSingleObject(m_h2, INFINITE); //等待子线程结束 ::CloseHandle(m_hMutex); //关闭句柄 ::CloseHandle(m_h1); ::CloseHandle(m_h2); system("pause"); return 0;}//用户线程1DWORD WINAPI my_thread1(LPVOID m_pParameter){ UINT* my_count = (UINT*)m_pParameter; cout << "thread1" << endl; for (int i = 0; i < *my_count; ++i) { ::WaitForSingleObject(m_hMutex, INFINITE); //等待互斥量 count = i; cout << count << "\t"; ::ReleaseMutex(&m_hMutex); //释放互斥量 } return 0;}//用户线程2DWORD WINAPI my_thread2(LPVOID m_pParameter){ UINT* my_count = (UINT*)m_pParameter; cout << "thread2" << endl; for (int i = 0; i < *my_count; ++i) { ::WaitForSingleObject(m_hMutex, INFINITE); //等待互斥量 count = i; cout << count << "\t"; ::ReleaseMutex(&m_hMutex); //释放互斥量 } return 0;}
转载地址:http://gfkhj.baihongyu.com/