一个i++的教训,多线程问题

原创 2015年11月19日 22:39:30

设计了一个ring buffer,一个中断进程负责往里面写入数据,一个后台进程负责读取数据。

数据每次写入就对cnt++,每次读取就cnt--,运行一段时间之后,发现写指针和读指针对不上了,中间隔开了一段距离。

查了很久,发现很有可能是这个cnt++出了问题,因为++操作不是原子操作,需要先mov出来,++,然后写回,这样的话有可能在中断里++之后又被原先被中断的--操作覆盖。

详细的过程分析:

1. CPU执行到cnt--,

2. cnt的值(架设==5)被mov到寄存器进行--操作

3. 寄存器完成操作得到结果4

4. 把寄存器的结果写回变量的内存地址,最终得到4.

假如在第2步之后发生了中断,那么情况是:

1. CPU执行到cnt--,

2. cnt的值(架设==5)被mov到寄存器进行--操作

3. 发生中断,中断程序把临时变量入栈,保护现场,也就是把寄存器里cnt=5保存起来

4. 中断里面获取cnt的值,也是5,放入寄存器进行++运算

5. 把运算结果6写回变量的内存地址,此时内存里的值为6

6. 中断程序退出之前恢复现场,把之前的变量出栈,寄存器恢复为5并进行--运算

7. 寄存器完成操作得到结果4

8. 把寄存器的结果写回变量的内存地址,最终得到4.

这样,最终的结果就好比根本没用执行cnt++,实际上只执行了cnt--。


解决的办法:

暂时我想到的是,在需要做cnt--之前先关闭中断,等完成后重新打开中断。





线程安全性---面试题--i++的线程安全性问题

这个类真的非常实用,更重要的是 它确实非常简单: 附上自己的代码,可以自己试试: AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安...

高并发的epoll+多线程

转载自:http://blog.chinaunix.net/uid-311680-id-2439721.html epoll是linux下高并发服务器的完美方案,因为是基于事件触发的,所以比se...

python多线程、异步、多进程+异步爬虫

安装Tornadopip install tornado python的多线程比较鸡肋,使用tornado可以实现异步的爬取,代码也比较简单,使用了coroutine后也可以不用回调了。代码如下,最...

VC++实现多线程ddos

#include #include   #include #pragma comment(lib,"ws2_32.lib") #define SEQ 0x28376839 int...

Thinking in Java---多线程仿真:银行出纳员仿真+饭店仿真+汽车装配工厂仿真

多线程一个很有意思的作用就是用于仿真,这篇博客就会结合几个仿真实例来综合运用一下前面所学的多线程并发知识。一.银行出纳员仿真 问题描述:银行会有很多来办业务的顾客,他们会排队等待服务;对于银行方面他...
  • acm_lkl
  • acm_lkl
  • 2016年02月27日 10:41
  • 1628

一个有意思的小程序,考验多线程问题能力

题目: 1. 某银行有至多三个窗口提供服务。 2. 该银行每天至多服务100人次; 3. 初始时,只有一个窗口开放,如果等待人数超过两人(包含正在办理业务的人),才开放下一个窗口。 模拟业务办理过程:...
  • xeseo
  • xeseo
  • 2013年07月25日 12:15
  • 587

GDB多线程调试基本命令和实现简介以及一个常见问题的解决

先介绍一下GDB多线程调试的基本命令。 info threads 显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。前面有*的是当前调试的线程。...

windows下多线程(生产者消费者问题:3个生产者,一个消费者,4个缓冲区)

原作者提供源码为两种情况: 第一种:1生产者1消费者1缓冲区 第二种:1生产者 2消费者 4缓冲区 ========================下面为修改作者源码得到的 3个生产者1个消...

从零开始实现Java多线程数据库连接池(附一个神秘的问题)

本例采用mysql数据库,因此请先下载mysql-connection.jar 众所周知,创建数据库连接需要消耗较多的资源,且创建时间也较长。如果网站一天100万PV(假设每个页面都有DB读取或修改操...
  • soonfly
  • soonfly
  • 2017年05月25日 16:54
  • 3467

答疑一个哥们的多线程问题关于 start()和run()

之所以出现线程,就是为了更好的利用CPU,让她更加“精明”的干活。 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。 然后通过此Thread类调用方...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一个i++的教训,多线程问题
举报原因:
原因补充:

(最多只允许输入30个字)