欢迎光临散文网 会员登陆 & 注册

秒杀多线程-原子操作

2023-01-30 20:55 作者:ベ计院小白隆ミ  | 我要投稿

前面章节:



原子操作 Interlocked系列函数

对于多线程报数功能,为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是否运行出错。这也非常类似于统计一个网站每天有多少用户登录,每个用户登录用一个线程模拟,线程运行时会将一个表示计数的变量递增。程序在最后输出计数的值表示有今天多少个用户登录,如果这个值不等于我们启动的线程个数,那显然说明这个程序是有问题的。整个程序代码如下:

程序输出的结果好象并没什么问题。下面增加点用户来试试,现在模拟50个用户登录,为了便于观察结果,在程序中将50个用户登录过程重复20次,代码如下:

可以发现输出结果是不确定的。查看g_iLoginCount++;操作的汇编代码(VS可以调试查看):

g_iLoginCount++;操作的汇编代码

第一条汇编就是将g_iLoginCount的值读取到寄存器eax中第二条汇编就是将寄存器eax的值与1相加,并将结果存入寄存器eax中第三条汇编就是将寄存器eax中的值写回内存中

这样由于线程执行的并发性,很可能线程A执行到第二句时,线程B开始执行,线程B将原来的值又写入寄存器eax中,这样线程A所主要计算的值就被线程B修改了。这样执行下来,结果是不可预知的——可能会出现50,可能小于50。

因此在多线程环境中对一个变量进行读写时,需要有一种方法能够保证对一个值的递增操作是原子操作——即不可打断性,一个线程在执行原子操作时,其它线程必须等待它完成之后才能开始执行该原子操作。Windows系统提供了一些以Interlocked开头的函数来完成这一任务(Interlocked系列函数)。

常用的Interlocked系列函数:

1.递增/减

2.指定增加或减少的值

3.赋值

修改代码:

InterlockedIncrement((LPLONG)&g_iLoginCount);的汇编代码

只有一条汇编

引入原子操作运行结果

因此,在多线程环境下,我们对变量的自增自减这些简单的语句也要慎重思考,防止多个线程导致的数据访问出错。更多介绍,请访问http://msdn.microsoft.com/zh-cn/library/aa909196.aspx

如果模拟100个用户登录会有意想不到的结果,可以试试,看一下运行结果


下一篇介绍一个经典的多线程问题


参考:https://blog.csdn.net/morewindows/article/details/7429155


秒杀多线程-原子操作的评论 (共 条)

分享到微博请遵守国家法律