孙鑫 第十五/十六课之一 线程同步Mutex

来源:互联网 发布:php二次开发 编辑:程序博客网 时间:2024/05/17 00:09

说明

windows线程同步的方法主要有

互斥对象Mutex、

事件对象Event、

临界区CriticalSection、

信号量Semaphore。


下面将依次说明。

 

1 互斥对象

互斥对象是内核对象,包含一个使用数量,一个线程ID(标识当前拥有该对象的线程ID),一个计数器(当拥有该对象的线程多次请求该对象时也可以再次获得该对象,同时计数器增加次数,在释放该对象的时候也要释放相应次数)。

一个原则:谁拥有谁释放。

NOTE:当拥有该对象的线程退出时并且没有释放该对象,那么不管该线程请求了几次互斥对象,操作系统都会收回,并将计数器清零。

互斥量可以保证某一时刻只能有一个线程访问受保护的资源(代码段或变量等)。

 

①创建互斥对象

HANDLE   CreateMutex(

LPSECURITY_ATTRIBUTES  lpMutexAttributes,  //安全属性,可为NULL 默认安全属性

BOOL bInitOwner, //初始创建后,创建该互斥对象的线程是否拥有该对象

LPCTSTR  lpName //对象名字,可为NULL,当要限制在内存中只有一个该对象的实例时要命名,根据该函数返回值判断是否已经存在。

);

eg.

HANDLE hMutex = CreateMutex(NULL, TRUE, "test");  //默认安全属性,初始创建该对象的线程拥有该对象,命名为test

if(hMutex) //如果创建了对象

{

    if( ERROR_ALREADY_EXITS == GetLastError() ) //名为test的对象已经存在内存中

    {

        MessageBox("已经存在该对象的实例");

        return;

    }

    //codes

}

//codes




②等待对象

DWORD  WaitForSingleObject(

HANDLE hHandle,  //等待的对象句柄

DWORD dwMilliseconds  //等待时间,单位ms,如果为INFINITE则为无限期等待

); 

返回值:

WAIT_ABANDONED:拥有互斥对象的线程结束前没有释放mutex,根据需要决定是否要继续执行

WAIT_OBJECT_0:在等待时间内等到该对象

WAIT_TIMEOUT:等待超时,根据需要决定是否要继续执行

eg.

WaitForSingleObject(hMutex, INFINITE);  //无限期等待该对象 

 

③释放对象

BOOL  ReleaseMutex(

HANDLE   hMutex

);

释放hMutex对象

eg.

ReleaseMutex(hMutex);

 

 

2 实例

////////////////////////////////////My73MutexDlg.h 类声明中/////////////////////////////////////////////

private:

    static HANDLE m_hMutex;


public:

    static UINT MyThread1(LPVOID lpParam);

    static UINT MyThread2(LPVOID lpParam);

 

 

////////////////////////////////////My73MutexDlg.cpp 类定义中///////////////////////////////////////////

HANDLE CMy73MutexDlg::m_hMutex = INVALID_HANDLE_VALUE;

 

//对话框初始化

BOOL  OnInitDialog()

{

    //codes

    m_hMutex = CreateMutex(NULL, TRUE, "test"); //主线程有信号

    if (m_hMutex)

    {

        if (ERROR_ALREADY_EXISTS == GetLastError())

        {

            MessageBox("只能打开一个实例");

            return FALSE;

        }

    }

    CWinThread* pThread1 = AfxBeginThread(MyThread1, (LPVOID)&m_ctrlEdit1);

    CWinThread* PThread2 = AfxBeginThread(MyThread2, (LPVOID)&m_ctrlEdit2); 

 

    //主线程再次请求该互斥对象,仍然可以获得该互斥对象,对象内计数器加1

    WaitForSingleObject(m_hMutex, INFINITE);

    ReleaseMutex(m_hMutex);  //主线程释放该对象

    ReleaseMutex(m_hMutex);  //主线程要释放2次,使得计数器为0

 

    //codes

    return TRUE;

}

 

 

//线程函数1

UINT CMy73MutexDlg::MyThread1(LPVOID lpParam)

{

    int a = 0;

    CString str;

    CEdit* pEdit = (CEdit*)lpParam;

    while (true)

    {

        WaitForSingleObject(m_hMutex, INFINITE); //请求互斥对象

        str.Format("%d", ++a);

        pEdit->SetWindowText(str); 

        Sleep(2000);

        ReleaseMutex(m_hMutex); //释放互斥对象

    }

    return 0;

}

 



//线程函数2

UINT CMy73MutexDlg::MyThread2(LPVOID lpParam)

{

    int b = 0;

    CString str;

    CEdit* pEdit = (CEdit*)lpParam;

    while(true)

    {

        if(WAIT_ABANDONED == WaitForSingleObject(m_hMutex, INFINITE)) //如果拥有互斥对象的线程退出时没有释放mutex

        {

            AfxMessageBox("abandoned");

            //根据需要决定是不是要继续往下执行

        }

        str.Format("%d", ++b);

        pEdit->SetWindowText(str);

        Sleep(2000);

        ReleaseMutex(m_hMutex);

    }

    return 0;

}



孙鑫 第十五/十六课之一 线程同步Mutex - 大灰狼 - 大灰狼 的博客

  

 

 

原创粉丝点击