zoukankan      html  css  js  c++  java
  • 互斥对象锁和临界区锁性能比较(临界区效率更高,互斥可用于多进程的多线程中)

    classnull测试工作system
        在Win32平台上进行多线程编程,常会用到锁。下边用C++实现了互斥对象(Mutex)锁和临界区(CRITICAL_SECTION)锁,以加深理解和今后方便使用。代码已在VS2005环境下编译测试通过。
    Lock.h
    [cpp] view plaincopy
    #ifndef _Lock_H  
    #define _Lock_H  
      
    #include <windows.h>  
      
      
    //锁接口类  
    class ILock  
    {  
    public:  
        virtual ~ILock() {}  
      
        virtual void Lock() const = 0;  
        virtual void Unlock() const = 0;  
    };  
      
    //互斥对象锁类  
    class Mutex : public ILock  
    {  
    public:  
        Mutex();  
        ~Mutex();  
      
        virtual void Lock() const;  
        virtual void Unlock() const;  
      
    private:  
        HANDLE m_mutex;  
    };  
      
    //临界区锁类  
    class CriSection : public ILock  
    {  
    public:  
        CriSection();  
        ~CriSection();  
      
        virtual void Lock() const;  
        virtual void Unlock() const;  
      
    private:  
        CRITICAL_SECTION m_critclSection;  
    };  
      
      
    //
    class CMyLock  
    {  
    public:  
        CMyLock(const ILock&);  
        ~CMyLock();  
      
    private:  
        const ILock& m_lock;  
    };  
      
      
    #endif  
    Lock.cpp
    [cpp] view plaincopy
    #include "Lock.h"  
      
    //---------------------------------------------------------------------------  
      
    //创建一个匿名互斥对象  
    Mutex::Mutex()  
    {  
        m_mutex = ::CreateMutex(NULL, FALSE, NULL);  
    }  
      
    //销毁互斥对象,释放资源  
    Mutex::~Mutex()  
    {  
        ::CloseHandle(m_mutex);  
    }  
      
    //确保拥有互斥对象的线程对被保护资源的独自访问  
    void Mutex::Lock() const  
    {  
        DWORD d = WaitForSingleObject(m_mutex, INFINITE);  
    }  
      
    //释放当前线程拥有的互斥对象,以使其它线程可以拥有互斥对象,对被保护资源进行访问  
    void Mutex::Unlock() const  
    {  
        ::ReleaseMutex(m_mutex);  
    }  
      
    //---------------------------------------------------------------------------  
      
    //初始化临界资源对象  
    CriSection::CriSection()  
    {  
        ::InitializeCriticalSection(&m_critclSection);  
    }  
      
    //释放临界资源对象  
    CriSection::~CriSection()  
    {  
        ::DeleteCriticalSection(&m_critclSection);  
    }  
      
    //进入临界区,加锁  
    void CriSection::Lock() const  
    {  
        ::EnterCriticalSection((LPCRITICAL_SECTION)&m_critclSection);  
    }     
      
    //离开临界区,解锁  
    void CriSection::Unlock() const  
    {  
        ::LeaveCriticalSection((LPCRITICAL_SECTION)&m_critclSection);  
    }  
      
    //---------------------------------------------------------------------------  
      
    //利用C++特性,进行自动加锁  
    CMyLock::CMyLock(const ILock& m) : m_lock(m)  
    {  
        m_lock.Lock();  
    }  
      
    //利用C++特性,进行自动解锁  
    CMyLock::~CMyLock()  
    {  
        m_lock.Unlock();  
    }  
    // MyLock.cpp : 定义控制台应用程序的入口点。  
    //  
      
    #include <iostream>  
    #include <process.h>  
    #include <time.h>  
    #include "Lock.h"  
      
    using namespace std;  
      
      
    #define ENABLE_MUTEX  
    #define ENABLE_CRITICAL_SECTION  
      
      
    #if defined (ENABLE_MUTEX)  
      
    //创建一个互斥对象类型锁  
    Mutex g_Lock;  
      
    #elif defined (ENABLE_CRITICAL_SECTION)  
      
    //创建一个临界区类型锁  
    CriSection g_Lock;  
      
    #endif  
      
      
    void LockCompare(int &iNum)  
    {  
        CMyLock lock1(g_Lock);  
      
        iNum++;  
    }  
      
      
    //线程函数  
    unsigned int __stdcall StartThread(void *pParam)  
    {  
        char *pMsg = (char *)pParam;  
        if (!pMsg)  
        {  
            return (unsigned int)1;  
        }  
      
        CMyLock lock2(g_Lock);  
      
        clock_t tStart,tEnd;  
      
        tStart = clock();  
      
        int iNum = 0;  
        for (int i = 0; i < 100000; i++)  
        {  
            LockCompare(iNum);  
        }  
          
        tEnd = clock();  
    #if defined (ENABLE_MUTEX)  
      
        cout<<"The lock type is mutex, time = "<<(tEnd - tStart)<<" ms."<<endl;  
      
    #elif defined (ENABLE_CRITICAL_SECTION)  
      
        cout<<"The lock type is critical section, time = "<<(tEnd - tStart)<<" ms."<<endl;  
      
    #endif  
      
        return (unsigned int)0;  
    }  
      
    int main(int argc, char* argv[])  
    {  
        HANDLE hThread1, hThread2;  
        unsigned int uiThreadId1, uiThreadId2;  
      
        char *pMsg1 = "First print thread.";  
        char *pMsg2 = "Second print thread.";  
      
        //创建两个工作线程,分别打印不同的消息  
        hThread1 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg1, 0, &uiThreadId1);  
        hThread2 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg2, 0, &uiThreadId2);  
      
        //等待线程结束  
        DWORD dwRet = WaitForSingleObject(hThread1,INFINITE);  
        if ( dwRet == WAIT_TIMEOUT )  
        {  
            TerminateThread(hThread1,0);  
        }  
        dwRet = WaitForSingleObject(hThread2,INFINITE);  
        if ( dwRet == WAIT_TIMEOUT )  
        {  
            TerminateThread(hThread2,0);  
        }  
      
        //关闭线程句柄,释放资源  
        ::CloseHandle(hThread1);  
        ::CloseHandle(hThread2);  
      
        system("pause");  
        return 0;  
    }  
    
        在线程函数StartThread中,循环100000次,对保护资源“iNum ”反复加锁,解锁。编译,运行5次,将每次打印的线程锁切换耗时时间记录下来。之后,将测试代码中的宏 #define ENABLE_MUTEX 注释掉,禁掉互斥锁,启用临界区锁,重新编译代码,运行5次。下边是分别是互斥锁和临界区锁耗时记录(不同机器上耗时会不同):
    
    互斥锁
    线程Id
    耗时 / ms
    总计
    1
    141
    125
    125
    125
    125
    641
    2
    140
    125
    140
    125
    156
    686
     
    临界区锁
    线程Id
    耗时 / ms
    总计
    1
    15
    16
    31
    31
    31
    124
    2
    31
    31
    31
    16
    31
    140
     
     
        互斥锁总共耗时:641+686=1327 ms,而临界区锁:124+140=264 ms。显而易见,临界区锁耗时比互斥锁耗时节约了大概5倍的时间。
        总结:1、在同一个进程的多线程同步锁,宜用临界区锁,它比较节约线程上下文切换带来的系统开销。但因临界区工作在用户模式下,所以不能对不同进程中的多线程进行同步。2、因互斥对象锁属于内核对象,所以在进行多线程同步时速度会比较慢,但是可以在不同进程的多个线程之间进行同步。
    

      

  • 相关阅读:
    Spring+JCaptcha验证码使用示例
    Hibernate-Session使用的背后
    DWR+Spring配置使用
    Spring+Quartz配置定时任务
    利用HtmlParser解析网页内容
    利用HttpClient4访问网页
    利用Common-Fileupload上传文件图片
    利用Common-BeanUtils封装请求参数
    浮点数的一点东西
    基数排序——浮点数结构体进阶
  • 原文地址:https://www.cnblogs.com/profession/p/4533878.html
Copyright © 2011-2022 走看看