原子变量自增的实现

94 篇文章 2 订阅
53 篇文章 2 订阅

原子变量自增大致有两种方式;一种是基于CPU硬件支持,而另一种为软件层面自旋实现;两者各有各的优势;理论上说软件

层面的现实是最通用的,不过它也带来了一些棘手的问题比如每个线程都在高频率的执行原子自增那么则会出现原子操作死锁,一

般它主要出现于基于原子信号的TTASLock自旋锁上面;正常情况下没有这么极端所有线程都因原子自增始修正而死循环;但这的确

是软件层面实现存在的一种缺陷。

下面先看原子自增函数的软件层面

        public static int Increment(ref int value)
        {
            int lOrignal, lNewValue;
            do
            {
                lOrignal = value;
                lNewValue = lOrignal + 1;
                value = lNewValue;
            } while (lNewValue != value);
            return lNewValue;
        }

上述代码若短时间内线程不需要很大量的持续使用时,那么是不会造成死循环的,那么造成死循环的原因在于lNewValue始终

法等于value由于其它的线程在读value中写入新的值到value 而它们在后置条件的测试中无法通过,过而造成的死循环;解决的办

法是一段周期还是不可就放弃写入返回ld_link当前值;另外必须要提的一点是你需要显示的告诉语言编译器与CLR当前操作的变量

是可要求编译器与CLR放弃对它的存储器读写优化,减少原子读写碰撞。

下面为基于CPU硬件支持的实现

int __fastcall InterlockedIncrement(volatile int* location)
{
	_asm
	{
		mov ecx, dword ptr[location]
		mov eax, 1
		lock xadd dword ptr[ecx], eax
		inc eax
	}
}
上述代码解决了软件层面实现的固有缺陷,但它却需要借助于CPU支持,从现实情况下它兼容从80486 CPU及以上的处理器都

支持它所使用的指令;所以现时代的PC不会存在不兼容的问题。

LOCK指令前缀,它用于标识后方的指令限定的操作存储区域,它可能是寄存器、内存;进行锁定;加以保护;其工作原理与一

般的加锁差异不大;唯一不同之处在于LOCK不保护临界代码,它只保护一次Instruction执行时对存储器的操作;

XADD指令与一般的ADD指令是不同的,它相对的有些特殊,一般向上类似的ADD运算在执行时会把右的寄存器的值与左地址

标识符、内的值相加后存储到左地址标识符内,但不影响到右值存储器的值,而XADD与ADD功能是几乎相同的,但它会把与寄存

器相加的之前的左地址标识符内的值存放到相加的寄存器内。

--------------------------------------------------

ADD ---- mem/reg | reg/immNOTE: IMM立即数;REG寄存器

XADD---- mem/reg | reg/imm

堆栈演化:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值