InterlockedIncrement和InterlockedDecrement的妙用

本文通过一个具体的应用案例,展示了如何使用Interlocked API确保在多线程环境下特定代码仅执行一次,有效解决多实例化问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般来说,在多用户线程环境中,我们使用临界区、事件对象甚至互斥量来进行同步,尤其是临界区,可以很方便地对某些变量甚至代码块进行锁定执行,防止多线程之间资源恶性抢夺。既然如此,为啥微软又单独提供了专用于一个数值锁定计算的API函数InterlockedIncrement和InterlockedDecrement呢?他们又有什么特殊作用呢?
    恰好近段时间写了一个这方面的应用,帮我加深了对这类API函数的理解。
    首先描述一下需求,在应用中,有这样一个类,它可能只被实例化一次,也可能会被实例化多次,但不管被实例化了几次,它必须在构造函数里执行一项初始化计算,假设初始化计算的函数为WSAStartup,同时还需要在析构函数里执行一下注销计算,假设注销计算的函数为WSACleanup,现在有一个要求,就是它们的初始化和注销计算只能被执行一次,就如同在一个项目中,只能运行一次WSAStartup和WSACleanup一样。当然,大家可能会想到直接在工程的开始和结尾处实现这样的功能,但是,如果把这个类的文件包括在其它测试工程里进行测试,同时不改变其它工程的代码,又该如何实现呢?
    其实,我们可以充分利用InterlockedIncrement和InterlockedDecrement,就如同COM的CoInitialize()和CoUninitialize()一样,描述代码如下:

    假设类名为A:

view plaincopy to clipboardprint?
class A  
{  
protected:  
    static long     m_nRef;  
public:  
    //类A的构造函数  
    A()  
    {  
        if(1 == InterlockedIncrement(&m_nRef))  
        {  
            //以下代码只执行一次  
            WSADATA wsaData;  
            WSAStartup(MAKEWORD(2,2), &wsaData);  
        }  
    };  
 
    //类A的虚析构函数  
    virtual ~A()  
    {  
        if(0 == InterlockedDecrement(&m_nRef))  
        {  
            //以下代码只执行一次  
            WSACleanup();  
        }  
    }  
};  
long A::m_nRef = 0; 
class A
{
protected:
 static long  m_nRef;
public:
 //类A的构造函数
 A()
 {
  if(1 == InterlockedIncrement(&m_nRef))
  {
   //以下代码只执行一次
   WSADATA wsaData;
   WSAStartup(MAKEWORD(2,2), &wsaData);
  }
 };

 //类A的虚析构函数
 virtual ~A()
 {
  if(0 == InterlockedDecrement(&m_nRef))
  {
   //以下代码只执行一次
   WSACleanup();
  }
 }
};
long A::m_nRef = 0;
 

    这样,无论我们创建了类A的多少个实例,在类的构造函数和析构函数里,WSAStartup和WSACleanup均只被执行一次,有效地保证了单元代码的封装性。

 

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/lyserver/archive/2010/02/04/5289265.aspx

C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9878): error C2065: “InterlockedIncrement64”: 未声明的标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9910): error C2065: “InterlockedDecrement64”: 未声明的标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9946): error C3861: “InterlockedExchange64”: 找不到标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(10000): error C3861: “InterlockedExchangeAdd64”: 找不到标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(10010): error C3861: “InterlockedExchangeAdd64”: 找不到标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(10057): error C3861: “InterlockedAnd64”: 找不到标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(10067): error C3861: “InterlockedOr64”: 找不到标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(10077): error C3861: “InterlockedXor64”: 找不到标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt\wrl\implements.h(1570): error C3861: “InterlockedCompareExchangeNoFence”: 找不到标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt\wrl\implements.h(1588): error C3861: “InterlockedCompareExchangeRelease”: 找不到标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt\wrl\implements.h(1874): error C2065: “_ARM64_BARRIER_ISH”: 未声明的标识符 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt\wrl\implements.h(1874): error C3861: “__dmb”: 找不到标识符 src\Candidate\EnumTfCandidates.cpp(78): error C2665: “InterlockedIncrement”: 没有重载函数可以转换所有参数类型 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9874): note: 可能是“unsigned __int64 InterlockedIncrement(volatile unsigned __int64 *)” src\Candidate\EnumTfCandidates.cpp(78): note: “unsigned __int64 InterlockedIncrement(volatile unsigned __int64 *)”: 无法将参数 1 从“LONG *”转换为“volatile unsigned __int64 *” src\Candidate\EnumTfCandidates.cpp(78): note: 指向的类型不相关; 转换需要 reinterpret_cast、C 样式强制转换或带圆括号的函数样式强制转换 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9862): note: 或 “unsigned long InterlockedIncrement(volatile unsigned long *)” src\Candidate\EnumTfCandidates.cpp(78): note: “unsigned long InterlockedIncrement(volatile unsigned long *)”: 无法将参数 1 从“LONG *”转换为“volatile unsigned long *” src\Candidate\EnumTfCandidates.cpp(78): note: 指向的类型不相关; 转换需要 reinterpret_cast、C 样式强制转换或带圆括号的函数样式强制转换 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9853): note: 或 “unsigned int InterlockedIncrement(volatile unsigned int *)” src\Candidate\EnumTfCandidates.cpp(78): note: “unsigned int InterlockedIncrement(volatile unsigned int *)”: 无法将参数 1 从“LONG *”转换为“volatile unsigned int *” src\Candidate\EnumTfCandidates.cpp(78): note: 指向的类型不相关; 转换需要 reinterpret_cast、C 样式强制转换或带圆括号的函数样式强制转换 src\Candidate\EnumTfCandidates.cpp(78): note: 尝试匹配参数列表“(LONG *)”时 src\Candidate\EnumTfCandidates.cpp(83): error C2665: “InterlockedDecrement”: 没有重载函数可以转换所有参数类型 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9906): note: 可能是“unsigned __int64 InterlockedDecrement(volatile unsigned __int64 *)” src\Candidate\EnumTfCandidates.cpp(83): note: “unsigned __int64 InterlockedDecrement(volatile unsigned __int64 *)”: 无法将参数 1 从“LONG *”转换为“volatile unsigned __int64 *” src\Candidate\EnumTfCandidates.cpp(83): note: 指向的类型不相关; 转换需要 reinterpret_cast、C 样式强制转换或带圆括号的函数样式强制转换 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9894): note: 或 “unsigned long InterlockedDecrement(volatile unsigned long *)” src\Candidate\EnumTfCandidates.cpp(83): note: “unsigned long InterlockedDecrement(volatile unsigned long *)”: 无法将参数 1 从“LONG *”转换为“volatile unsigned long *” src\Candidate\EnumTfCandidates.cpp(83): note: 指向的类型不相关; 转换需要 reinterpret_cast、C 样式强制转换或带圆括号的函数样式强制转换 C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um\winbase.h(9885): note: 或 “unsigned int InterlockedDecrement(volatile unsigned int *)” src\Candidate\EnumTfCandidates.cpp(83): note: “unsigned int InterlockedDecrement(volatile unsigned int *)”: 无法将参数 1 从“LONG *”转换为“volatile unsigned int *” src\Candidate\EnumTfCandidates.cpp(83): note: 指向的类型不相关; 转换需要 reinterpret_cast、C 样式强制转换或带圆括号的函数样式强制转换 src\Candidate\EnumTfCandidates.cpp(83): note: 尝试匹配参数列表“(LONG *)”时 > in src\Candidate\EnumTfCandidates.cpp PS D:\Downloads\MetasequoiaImeTsf-master\MetasequoiaImeTsf - 副本>
最新发布
06-17
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值