[系统级] 汇编实现旋转锁

本文详细解析了自旋锁的工作机制,包括宏定义、关键指令cmpxchg、测试与递增操作的封装,以及自旋等待与解锁的实现。通过实例代码展示了如何使用自旋锁来解决多线程并发问题,特别强调了汇编语言在提高性能方面的应用。

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

windows库已经提供了旋转锁的函数,为什么我们还要自己实现呢?因为汇编快啊!

加锁

先定义宏:

#define INTERLOCKED_INCREMENT(A,B)			\
	__asm	mov eax,0				\
	__asm	mov ecx,A				\
	__asm	mov edx,1				\
	__asm	lock cmpxchg dword ptr [ecx],edx	\
	__asm	mov B,eax
A代表临界资源当前是否被其他线程占用,只有0和1两种取值;B表示是否需要自旋等待,也只有0和1两种取值。

最关键的是cmpxchg句,cmpxchg指令将累加器AL/AX/EAX/RAX中的值与首操作数(目的操作数)比较,如果相等,第2操作数(源操作数)的值装载到首操作数,zf置1;如果不等, 首操作数的值装载到AL/AX/EAX/RAX并将zf清0。

我们这里不关心zf,总结而言:

当A为0时,首操作数[ecx]与eax相等(都为0),于是将源操作数edx(值为1)装载到首操作数,即将A置为1,以将其他线程拒之门外,最后将B置为0,表示资源抢占成功;

当A为1时,首操作数[ecx]与eax不相等,于是首操作数[ecx]装载到eax,eax值变为1,最后B被置为1,表示资源尚未抢占成功。

光有INTERLOCKED_INCREMENT(A,B)当然还不够,需要做如下封装:

void SpinLockEx(long *SystemSpinLockSection)
{
	int k;

	INTERLOCKED_TEST_INCREMENT(SystemSpinLockSection,k);
	while (k)
	{
		Sleep(0);
		INTERLOCKED_TEST_INCREMENT(SystemSpinLockSection,k);
	}
}

如果SystemSpinLockSection为0,跑上来k就被置为0,那么while(k)就被跳过,我们已经抢占到了资源,就不需要自旋等待了;

如果SystemSpinLockSection为1,那么k就被置为1,自旋等待,直到突然有一天,SystemSpinLockSection成了0,那么k变成0就可以跳出循环了。

解锁

也先来段宏:

#define INTERLOCKED_DECREMENT(A)			\
	__asm	mov eax,0FFFFFFFFh			\
	__asm	mov ecx,A				\
	__asm	lock xadd dword ptr [ecx],eax
解锁的处理就比加锁简单多了,xadd指令将eax累加到[ecx]中,0FFFFFFFFh的十进制值就是-1,于是INTERLOCKED_DECREMENT(A)就是简单地将A递减,即由1置为0。

接口封装如下:

void SpinUnlockEx(long *SystemSpinLockSection)
{
	INTERLOCKED_DECREMENT(SystemSpinLockSection);
}

大功告成~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值