1、 Code

int	Work()
{
while (m_lInterlockedData < 10)
{
InterlockedIncrement(&m_lInterlockedData);
Sleep(100);
} printf("CInterlocked::Work end\n"); return 0;
}
起5个线程运行Work()函数,理论上m_lInterlockedData最后运行的结果应该是10。
BOOL	RunThread()
{
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL)); return TRUE;
}

2、 运行结果

实际运行结果却令人意外,m_lInterlockedData = 11, why?
3、 原因
做以下假设:
3.1 当m_lInterlockedData = 9时,线程1 运行完while(m_lInterlockedData < 10) ,会判断为真。
3.2 此时系统切换到线程2 运行,线程2的Work函数会将m_lInterlockedData增加到10。
3.3 系统再次切换返回到线程1运行,由于while的判定代码已执行且为真,所以此时会执行InterlockedIncrement(&m_lInterlockedData);从而将m_lInterlockedData再次增加到11。
4、 解决方法
改用临界区即可解决如上问题
int	WorkEx()
{
while (TRUE)
{
EnterCriticalSection(&m_cs);
if (m_lInterlockedData < 10)
{
m_lInterlockedData++;
LeaveCriticalSection(&m_cs);
}
else
{
LeaveCriticalSection(&m_cs);
break;
} Sleep(100);
} printf("CInterlocked::Work end\n"); return 0;
}

注意,为了不让在临近区中等待过久,故将Sleep(100) 放在LeaveCriticalSection() 之外。

Interlocked系列函数线程同步的缺陷的更多相关文章

  1. 原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  2. (转)原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  3. 多线程面试题系列(3):原子操作 Interlocked系列函数

    上一篇中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是否运行出错.这也非常类似于统计一个网站每天有多少用户登录,每个用户登录用一个线程模拟,线程运行时会将 ...

  4. 多线程--原子操作 Interlocked系列函数

    [转]原文地址:http://blog.csdn.net/morewindows/article/details/7429155 线程同步与互斥: 互斥主要指多个线程不能同时访问一个资源,如打印机就是 ...

  5. 多线程笔记--原子操作Interlocked系列函数

    前面写了一个多线程报数的功能,为了描述方便和代码简洁起见,只输出最后的报数结果来观察程序运行结果.这非常类似一个网站的客户访问统计,每个用户登录用一个线程模拟,线程运行时将一个表示计数的变量递增.程序 ...

  6. 秒杀多线程第三篇 原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  7. [OS] 多线程--原子操作 Interlocked系列函数

    转自:http://blog.csdn.net/morewindows/article/details/7429155 上一篇<多线程--第一次亲密接触 CreateThread与_begint ...

  8. 读书笔记——Windows核心编程(8)Interlocked系列函数

    先让我们来复习下小学知识 A+B=C//式中A为被加数,B为加数. A-B=C//式中A为被减数,B为减数. 再让我们来明确一个知识点:返回值为void的Windows函数意味着一定会执行成功. -- ...

  9. 线程系列3--Java线程同步通信技术

    上一篇文章我们讲解了线程间的互斥技术,使用关键字synchronize来实现线程间的互斥技术.根据不同的业务情况,我们可以选择某一种互斥的方法来实现线程间的互斥调用.例如:自定义对象实现互斥(sync ...

随机推荐

  1. 【转】UTF-8汉字正则表达式

    原文链接:http://blog.csdn.net/wide288/article/details/30066639 $str = "编程";// if(!preg_match(& ...

  2. ASP.NET登录控件login。

    1.Login控件.通常情况下会出现3个核心元素.用户名文本框.密码输入框.提交凭证的按钮. 1>.比较重要的属性:CreateUserText属性:包含站点注册页的链接文本.CreateUse ...

  3. jbox演示30种不同的调用方法

     在线预览 插件说明 - jbox 是一款基于 jQuery 的多功能对话框插件,能够实现网站的整体风格效果,给用户一个新的视觉享受. 运行环境 - 兼容 IE6+.Firefox.Chrome.Sa ...

  4. git常用命令表

    本文主要是用来记录一些在git管理的项目中常见的场景及其对应的命令,方便自己和他人使用的时候快速查询.如有不对,敬请指正. 查看某个git命令的帮助文档 git help [command] 查看各个 ...

  5. 分享最新15个加速 Web 开发的框架和工具

    我们为开发人员挑选了15个最新的  Web 开发框架,你肯定尝试一下这些新鲜的框架,有的可能略微复杂,有的提供了很多的配置选项,也有一些窗口小部件和界面交互的选择.他们将帮助你创建更优秀的网站,提供给 ...

  6. 关于一些网络代理实现智能流量分流的研究(PAC脚本介绍及利用)

    因为工作原因,需要访问一些国外的网站(科学上网),但直接FQ并不方便,于是研究了一些代理软件,比如Nydus,Green等, 在Nydus的Proxy版本中发现了实现国内国外流量的智能分流的办法,通过 ...

  7. git stash提交PR的正确步骤&git squash技术

    1.git stash梳理 1.1git stash的克隆与同步 首先整理下git stash的逻辑是这样 在本地做出了新的修改,提交时显示当前的版本不是最新版本,这时就需要先pull一下自己代码仓库 ...

  8. NSoperation用法详解及与GCD的比较

    NSInvocationOperation // 基于一个对象和selector来创建操作.如果你已经有现有的方法来执行需要的任务,就可以使用这个类 NSInvocationOperation * o ...

  9. 【Android】友盟的自动更新组件

    前言 又好又专业的服务能帮开发者省很多时间.一开始做项目也准备自己来统计数据.自己做自动更新,随着使用友盟服务的时间增加,渐渐放弃了这种想法,转而研究如何更充分的使用,这里分享一下使用自动更新组件的心 ...

  10. 【问题排查】StringIndexOutOfBoundsException

    工作中遇到 java.lang.StringIndexOutOfBoundsException ,查看网上资料,总结如下 1.异常定义: Java API指出StringIndexOutOfBound ...