1.临界区

临界区:一次只允许一个线程进入直到离开

并发是指多个线程在同时执行:

  • 单核–(是分时执行,不是真正的同时)
  • 多核–(在某一个时刻,会同时有多个线程再执行)

同步则是保证在并发执行的环境中各个线程可以有序的执行

分析两条线程执行下面代码。

DWORD dwVal =0; //全局变量

线程中的代码:

dwVal ++;	//只有一行安全吗?

对应的汇编代码:

mov eax,[0x12345678] 
add eax,1 
mov [0x12345678],eax

如果在执行完 add eax,1 后产生了线程切换(系统时钟),第二个线程进来了:mov eax,[0x12345678]
add eax,1
mov [0x12345678],eax;
第二个线程已经把1写到全局变量里了,第一个线程突然恢复执行mov [0x12345678],eax写入全局变量里的值还是1。

两线程有序执行结果应该为2,但是它在执行完 add eax,1 后,产生了线程切换得到的数据是错误的。



继续上面把上面的3行汇编换成一行看看是否安全。

inc dword ptr ds:[0x12345678]

如果你的CPU是单核这样的解决方案是安全的,如果你当前的CPU是多核的可能会出现一种极端情况,两个CPU同时执行同一行代码。

将以上代码修改成

lock inc dword ptr ds:[0x12345678]	//多核多线程下 依旧安全

lock锁住了当前指令所在的那块内存,用了lock在某个时刻只能有一个CPU来读这块内存。

参考: kernel32.Interlockedincrement
原子操作相关的API:

Interlockedlncrement
InterlockedExchangeAdd
InterlockedFlushSList
InterlockedDecrement
InterlockedExchange
InterlockedPopEntrySList
InterlockedCompareExchange
InterlockedPushEntrySList

在这里插入图片描述

多行代码原子操作

关键代码A 	//N行代码要求原子操作
关键代码B	//单独加LOCK可以吗?
关键代码C

如果你的逻辑代码有很多行的话,每个关键代码加lock是没有办法保证的的代码逻辑是正确的。

临界区:一次只允许一个线程进入直到离开

DWORD dwFlag = 0;	//11实现临界区的方式就是加锁 
					//锁:全局变量进去加1 出去减1

if(dwFlag  == 0)//判断临界区是否处于打开状态
{
	dwFlag = 1;	//进入临界区
	...
	dwFlag = 0;	//离开临界区
}

上面的临界区是不安全的,比如线程1判断完临界区是可以进入的,还没有将临界区置1线程切换了,这样就会出现线程1和2同时进入临界区。

自己实现临界区
全局变量: Flag =0

进入临界区:
mov eax,1
lock xadd [Flag],eax
cmp eax,0 		//如果不是0就是有人进入临界区了
jz endLab 
dec [Flag] 		//减1 让当前线程等待Sleep..

endLab:
ret

离开临界区:
lock dec[Flag]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值