zoukankan      html  css  js  c++  java
  • 【转】用C++实现多线程Mutex锁(Win32)

    原作者:chexlong 原文地址:http://blog.csdn.net/chexlong/article/details/7051193

    本文目的:用C++和Windows的互斥对象(Mutex)来实现线程同步锁。

        准备知识:1,内核对象互斥体(Mutex)的工作机理,WaitForSingleObject函数的用法,这些可以从MSDN获取详情; 2,当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源。Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

        下边是我参考开源项目C++ Sockets的代码,写的线程锁类

    Lock.h

    1. #ifndef _Lock_H  
    2. #define _Lock_H  
    3.   
    4. #include <windows.h>  
    5.   
    6. //锁接口类  
    7. class IMyLock  
    8. {  
    9. public:  
    10.     virtual ~IMyLock() {}  
    11.   
    12.     virtual void Lock() const = 0;  
    13.     virtual void Unlock() const = 0;  
    14. };  
    15.   
    16. //互斥对象锁类  
    17. class Mutex : public IMyLock  
    18. {  
    19. public:  
    20.     Mutex();  
    21.     ~Mutex();  
    22.   
    23.     virtual void Lock() const;  
    24.     virtual void Unlock() const;  
    25.   
    26. private:  
    27.     HANDLE m_mutex;  
    28. };  
    29.   
    30. //锁  
    31. class CLock  
    32. {  
    33. public:  
    34.     CLock(const IMyLock&);  
    35.     ~CLock();  
    36.   
    37. private:  
    38.     const IMyLock& m_lock;  
    39. };  
    40.   
    41.   
    42. #endif  

    Lock.cpp

    1. #include "Lock.h"  
    2.   
    3. //创建一个匿名互斥对象  
    4. Mutex::Mutex()  
    5. {  
    6.     m_mutex = ::CreateMutex(NULL, FALSE, NULL);  
    7. }  
    8.   
    9. //销毁互斥对象,释放资源  
    10. Mutex::~Mutex()  
    11. {  
    12.     ::CloseHandle(m_mutex);  
    13. }  
    14.   
    15. //确保拥有互斥对象的线程对被保护资源的独自访问  
    16. void Mutex::Lock() const  
    17. {  
    18.     DWORD d = WaitForSingleObject(m_mutex, INFINITE);  
    19. }  
    20.   
    21. //释放当前线程拥有的互斥对象,以使其它线程可以拥有互斥对象,对被保护资源进行访问  
    22. void Mutex::Unlock() const  
    23. {  
    24.     ::ReleaseMutex(m_mutex);  
    25. }  
    26.   
    27. //利用C++特性,进行自动加锁  
    28. CLock::CLock(const IMyLock& m) : m_lock(m)  
    29. {  
    30.     m_lock.Lock();  
    31. }  
    32.   
    33. //利用C++特性,进行自动解锁  
    34. CLock::~CLock()  
    35. {  
    36.     m_lock.Unlock();  
    37. }  

        下边是测试代码

    1. // MyLock.cpp : 定义控制台应用程序的入口点。  
    2. //  
    3.   
    4. #include <iostream>  
    5. #include <process.h>  
    6. #include "Lock.h"  
    7.   
    8. using namespace std;  
    9.   
    10. //创建一个互斥对象  
    11. Mutex g_Lock;  
    12.   
    13.   
    14. //线程函数  
    15. unsigned int __stdcall StartThread(void *pParam)  
    16. {  
    17.     char *pMsg = (char *)pParam;  
    18.     if (!pMsg)  
    19.     {  
    20.         return (unsigned int)1;  
    21.     }  
    22.   
    23.     //对被保护资源(以下打印语句)自动加锁  
    24.     //线程函数结束前,自动解锁  
    25.     CLock lock(g_Lock);  
    26.   
    27.     for( int i = 0; i < 5; i++ )  
    28.     {  
    29.         cout << pMsg << endl;  
    30.         Sleep( 500 );  
    31.     }  
    32.   
    33.     return (unsigned int)0;  
    34. }  
    35.   
    36. int main(int argc, char* argv[])  
    37. {  
    38.     HANDLE hThread1, hThread2;  
    39.     unsigned int uiThreadId1, uiThreadId2;  
    40.   
    41.     char *pMsg1 = "First print thread.";  
    42.     char *pMsg2 = "Second print thread.";  
    43.   
    44.     //创建两个工作线程,分别打印不同的消息  
    45.   
    46.     //hThread1 = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)StartThread, (void *)pMsg1, 0, (LPDWORD)&uiThreadId1);  
    47.     //hThread2 = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)StartThread, (void *)pMsg2, 0, (LPDWORD)&uiThreadId2);  
    48.   
    49.     hThread1 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg1, 0, &uiThreadId1);  
    50.     hThread2 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg2, 0, &uiThreadId2);  
    51.   
    52.     //等待线程结束  
    53.     DWORD dwRet = WaitForSingleObject(hThread1,INFINITE);  
    54.     if ( dwRet == WAIT_TIMEOUT )  
    55.     {  
    56.         TerminateThread(hThread1,0);  
    57.     }  
    58.     dwRet = WaitForSingleObject(hThread2,INFINITE);  
    59.     if ( dwRet == WAIT_TIMEOUT )  
    60.     {  
    61.         TerminateThread(hThread2,0);  
    62.     }  
    63.   
    64.     //关闭线程句柄,释放资源  
    65.     ::CloseHandle(hThread1);  
    66.     ::CloseHandle(hThread2);  
    67.   
    68.     system("pause");  
    69.     return 0;  
    70. }  

        用VC2005编译,启动程序,下边是截图

        如果将测线程函数中的代码注视掉,重新编译代码,运行

    1. CLock lock(g_Lock);  

         则结果见下图

     

        由此可见,通过使用Mutex的封装类,即可达到多线程同步的目的。因Mutex属于内核对象,所以在进行多线程同步时速度会比较慢,但是用互斥对象可以在不同进程的多个线程之间进行同步。

        在实际应用中,我们通常还会用到临界区,也有叫做关键代码段的CRITICAL_SECTION,在下篇博客中,我将会把CRITICAL_SECTION锁添加进来,并且对Mutex和CRITICAL_SECTION的性能做以比较。

  • 相关阅读:
    考试
    aws代理
    ansible debug
    apollo docker 安装 使用镜像 idoop/docker-apollo
    java jvm 内存监控工具visualvm 的使用
    kong dashboard UI 的使用 (使用kong 对服务反向代理,以及解决跨域问题)
    git账号
    kong Gateway && PostgreSQL 的安装(docker)
    apollo 配置中心的安装与使用
    springboot 开发模式 dev
  • 原文地址:https://www.cnblogs.com/gkwang/p/4482933.html
Copyright © 2011-2022 走看看