InterLocked的几个函数

InterLockedIncrement and InterLockedDecrement

实现数的原子性加减。什么是原子性的加减呢?

举个例子:如果一个变量 Long value =0;

首先说一下正常情况下的加减操作:value+=1;

1:系统从Value的空间取出值,并动态生成一个空间来存储取出来的值;

2:将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束。


如果此时有两个Thread ,分别记作threadA,threadB。

1:threadA将Value从存储空间取出,为0;

2:threadB将Value从存储空间取出,为0;

3:threadA将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束,Value=1。

4:threadB将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束,Value=1。

最后Value =1 ,而正确应该是2;这就是问题的所在,InterLockedIncrement 能够保证在一个线程访问变量时其它线程不能访问。同理InterLockedDecrement。

LONG   InterlockedDecrement(  
      LPLONG   lpAddend       //   variable   address  
);  
属于互锁函数,用在同一进程内,需要对共享的一个变量,做减法的时候,  
防止其他线程访问这个变量,是实现线程同步的一种办法(互锁函数)
  
首先要理解多线程同步,共享资源(同时访问全局变量的问题),否则就难以理解。  
    
result   =   InterlockedDecrement(&SomeInt)  
    
如果不考虑多线程其实就是   result   =   SomeInt   -   1;  
    
但是考虑到多线程问题就复杂了一些。就是说如果想要得到我预期的结果并不容易。  
    
result   =   SomeInt   -   1;  
    
举例说:  
SomeInt如果==1;  
预期的结果result当然==0;  
    
但是,如果SomeInt是一个全程共享的全局变量情况就不一样了。  
C语言的"result   =   SomeInt   -   1;"  
在实际的执行过程中,有好几条指令,在指令执行过程中,其它线程可能改变SomeInt值,使真正的结果与你预期的不一致。  
    
所以InterlockedDecrement(&SomeInt)的执行过程是这样的  
{  
      __禁止其他线程访问   (&SomeInt)   这个地址  
    
      SomeInt   --;  
        
      move   EAX,   someInt;   //   设定返回值,C++函数的返回值   都放在EAX中,  
    
      __开放其他线程访问   (&SomeInt)   这个地址  
}  
    
但是实际上只需要几条指令加前缀就可以完成,以上说明是放大的。  
    
你也许会说,这有必要吗?   一般来说,发生错误的概率不大,但是防范总是必要的
如果不考虑多线程  
result   =   InterlockedDecrement(&SomeInt);  
就是result   =   SomeInt   -   1;  
如果SomeInt==1,result一定==0;  
    
但是,在多线程中如果SomeInt是线程间共享的全局变量,情况就不那么简单了。  
result   =   SomeInt   -   1;  
在CPU中,要执行好几条指令。在指令中间有可能SomeInt被线程修改。那实际的结果就不是你预期的结果了。  
    
InterlockedDecrement(&SomeInt)  
放大的过程,如下:  
{  
      __禁止其他线程访问   &SomeInt   地址;  
    
      SomeInt   --;  
        
      /其他线程不会在这里修改SomeInt值。   !!!!!!  
    
      mov   EAX,   SomeInt;   //C++   函数返回值   总放在EAX中。  
        
      __开放其他线程访问   &SomeInt   地址;  
}  

 
InterlockedCompareExchange属于互锁函数

  类似的还有下面的几个

  (1) LONG InterlockedExchangeAdd ( LPLONG Addend, LONG Increment );

  Addend为长整型变量的地址,Increment为想要在Addend指向的长整型变量上增加的数值(可以是负数)。这个函数的主要作用是保证这个加操作为一个原子访问。

  (2) LONG InterlockedExchange( LPLONG Target, LONG Value );

  用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。

  (3) PVOID InterlockedExchangePointer( PVOID *Target, PVOID Value );

  用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。

  (4) LONG InterlockedCompareExchange(

  LPLONG Destination, LONG Exchange, LONG Comperand );

  如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个参数指向的值。函数返回值为原始值。

  (5) PVOID InterlockedCompareExchangePointer (

  PVOID *Destination, PVOID Exchange, PVOID Comperand );

  如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个参数指向的值。函数返回值为原始值。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值