线程的互斥和同步(3)- Windows的互斥锁

什么是互斥锁/互斥量?

在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象;选自百度百科-互斥锁

同一时刻只有一个线程访问互斥锁,如果其他线程请求占用该互斥锁时,该请求锁的线程会被挂起。直到锁的拥有者释放该互斥锁,CPU调度到请求锁的线程占有该互斥锁,该线程被唤醒。


Windows中关于互斥锁的相关函数如下:

  • CreateCreateMutex (LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName); // 创建互斥锁
  • WaitForSingleObject (HANDLE hHandle, DWORD dwMilliseconds); // 等待请求占有互斥锁
  • ReleaseMutex (HANDLE hMutex); // 释放互斥锁

1. CreateCreateMutex 函数;表示创建一个互斥锁,
  • 参数 lpMutexAttributes : 表示安全属性,一般设置为 nullptr 表示默认安全属性。
  • 参数 bInitialOwner : 表示创建后是否立即拥有该互斥锁,TRUE 表示立即拥有; FALSE 表示不立即拥有。
  • 参数 lpName : 表示互斥锁的名称。可以设置互斥锁的名称,也可以通过名称在不同的线程中共享;如果不设置明证可以设为 nullptr
  • 返回值:成功返回互斥锁的句柄。失败返回 nullptr
2. WaitForSingleObject 函数;表示等待请求占有互斥锁:
  • 参数 hHandle : 句柄。该函数不仅仅可以用于请求互斥锁,也可以用于比如等待线程、进程的结束;等待信号量、互斥量的占有、和等到信号。
  • 参数 dwMilliseconds : 表示毫秒数。设置为 INFINITE 表示无限等待下去。
  • 返回值:
返回值说明
WAIT_FAILED表示函数 WaitForSingleObject 调用失败,可以通过函数 GetLastError() 获取错误码
WAIT_OBJECT_0表示成功等待到设置的对象
WAIT_TIMEOUT表示等待超时
WAIT_ABANDONED如果对象时Mutex,表示持有Mutex对象的线程已经结束,但是没有释放该互斥锁;此时该Mutex对象处于废弃状态。其行为未知,不建议使用
3. ReleaseMutex 函数,表示释放互斥锁。
  • 参数 hMutex 互斥锁的句柄

下面是个关于互斥锁的使用的简单示例,同样使用了 CThread

头文件:

class WinMutexThread : public CThread
{
public:
    void run(void) override;

    // 初始化Mutex,用于创建互斥锁
    static void initMutex(void);

private:
    // 互斥锁
    static HANDLE m_mutexHandle;
};

源文件:

#include <iostream>

HANDLE WinMutexThread::m_mutexHandle = nullptr;
int number = 0;

void WinMutexThread::run(void)
{
    while (1)
    {
        if (::WaitForSingleObject(m_mutexHandle, INFINITE) == WAIT_OBJECT_0)
        {
            std::cout << "Current Thread: " << ::GetCurrentThreadId() \
                      << ", Value: " << number++ << std::endl;

            ::ReleaseMutex(m_mutexHandle);
        }

        Sleep(1000);
    }
}

void WinMutexThread::initMutex(void)
{
    m_mutexHandle = ::CreateMutex(nullptr, FALSE, nullptr);
}

在run() 函数中,我们简单的请求互斥锁,并打印该线程ID和使全局变量的值自增1

调用

int main(int argc, char** argv)
{
    // 创建互斥锁
    WinMutexThread::initMutex();

    // 创建三个线程
    WinMutexThread thread1;
    WinMutexThread thread2;
    WinMutexThread thread3;
    // 开启线程
    thread1.start();
    thread2.start();
    thread3.start();
    // 等待
    thread1.wait();
    thread2.wait();
    thread3.wait();

    system("pause");
    return 0;
}

运行结果如下:
Current Thread: 12632, Value: 0
Current Thread: 13096, Value: 1
Current Thread: 18652, Value: 2
Current Thread: 12632, Value: 3
Current Thread: 13096, Value: 4
Current Thread: 18652, Value: 5
Current Thread: 12632, Value: 6
Current Thread: 13096, Value: 7
Current Thread: 18652, Value: 8
Current Thread: 12632, Value: 9
Current Thread: 13096, Value: 10
Current Thread: 18652, Value: 11

不会飞的纸飞机
扫一扫二维码,了解我的更多动态。

下一篇文章:线程的互斥和同步(4)- Qt中的互斥锁(QMutex和QMutexLocker)