互斥对象锁和临界区锁性能比较(临界区效率更高,互斥可用于多进程的多线程中)...

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、因互斥对象锁属于内核对象,所以在进行多线程同步时速度会比较慢,但是可以在不同进程的多个线程之间进行同步。

  

转载于:https://www.cnblogs.com/profession/p/4533878.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值