以下内容转自http://ifeve.com/race-conditions-and-critical-sections/

在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。如,同一内存区(变量,数组,或对象)、系统(数据库,web services等)或文件。实际上,这些问题只有在一或多个线程向这些资源做了写操作时才有可能发生,只要资源没有发生变化,多个线程读取相同的资源就是安全的。

多线程同时执行下面的代码可能会出错:

public class Counter {
protected long count = 0;
public void add(long value){
this.count = this.count + value;
}
}

想象下线程A和B同时执行同一个Counter对象的add()方法,我们无法知道操作系统何时会在两个线程之间切换。JVM并不是将这段代码视为单条指令来执行的,而是按照下面的顺序:

从内存获取 this.count 的值放到寄存器
将寄存器中的值增加value
将寄存器中的值写回内存

观察线程A和B交错执行会发生什么:

  this.count = 0;
A:读取 this.count 到一个寄存器 (0)
B:读取 this.count 到一个寄存器 (0)
B:将寄存器的值加2
B:回写寄存器值(2)到内存. this.count 现在等于 2
A:将寄存器的值加3
A:回写寄存器值(3)到内存. this.count 现在等于 3

两个线程分别加了2和3到count变量上,两个线程执行结束后count变量的值应该等于5。然而由于两个线程是交叉执行的,两个线程从内存中读出的初始值都是0。然后各自加了2和3,并分别写回内存。最终的值并不是期望的5,而是最后写回内存的那个线程的值,上面例子中最后写回内存的是线程A,但实际中也可能是线程B。如果没有采用合适的同步机制,线程间的交叉执行情况就无法预料。

竞态条件&临界区

当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。导致竞态条件发生的代码区称作临界区。上例中add()方法就是一个临界区,它会产生竞态条件。在临界区中使用适当的同步就可以避免竞态条件。

最新文章

  1. 文本比较算法:Needleman/Wunsch算法
  2. Android动画效果之初识Property Animation(属性动画)
  3. Mountains(CVTE面试题)解题报告
  4. spring 连接各种数据源的配置(转载)
  5. C#-DataTable分页代码
  6. THE HANDLER_READ_* STATUS VARIABLES
  7. JQuery onload、ready概念介绍及使用方法
  8. 编写类String的构造函数、析构函数和赋值函数
  9. Android 开源项目PhotoView源码分析
  10. 创建类模式(零):简单/静态工厂(Static Factory)
  11. ASP.NET MVC 中将FormCollection与实体间转换方法 (转)
  12. 策略模式 - OK
  13. Django开发环境配置
  14. js全选与反选
  15. Java中的会话管理——HttpServlet,Cookies,URL Rewriting(译)
  16. java中的引用传递问题
  17. python2.x 与 python3.x的不同
  18. Python_匿名函数
  19. hihocoder 前两题思路
  20. ABAP 内表(internal table) 标题行(header line) 工作区(work area) 简介 - [SAP]

热门文章

  1. KMP POJ 2406 Power Strings
  2. Jsp四个作用域page、request、session和application的区别
  3. 各种轮播实现(纯css实现+js实现)
  4. epoll IO多路复用(异步阻塞AIO)
  5. 浅谈.net remoting 与 webservice
  6. Spring+Spring MVC+Hibernate增查(使用注解)
  7. HTML 5 <aside> 标签
  8. day16-常用模块I(time、datetime、random、os、sys、json、pickle)
  9. Xamarin绑定ios静态库
  10. 12Java Bean