什么是竞态条件

官方的定义是如果程序运行顺序的改变会影响最终结果,这就是一个竞态条件(race condition).

 

理解竞态条件首先要知道程序运行不一定是线性的。初学编程的时候都是从“面向过程编程“开始的,一条一条指令打下来,期待着他们会顺序执行。debug的使用也加深了这一认识。不过事实上如果两条紧挨着的指令没有依赖关系,jvm是有可能将他们的运行顺序倒转的。当然这是题外话,最显著的“不按顺序执行“的例子还是多线程程序。

 

Runnable r1 = () -> { // do something };

Runnable r2 = () -> { // do another thing };

new Thread(r1).start();

new Thread(r2).start();

上述程序定义了两个Runnable实例,并用它们新建两个线程,虽然r1先于r2开始,但他们内部的代码谁先谁后就不由而知了。

 

如果一段程序运行多次的结果不一致(排除生成随机数的情况),那这就可能是竞态条件的体现。比如最典型的例子,两个线程同时把一个类的静态成员做50词自增加1的操作,即

 

SomeClass.someMember++;

写在两个线程中,都运行50次,运行结束以后用主线程去取这个变量的值几乎不可能是100. 有的时候是97,有的时候是98,这是用来说明竞态条件的最有效例子。

 

竞态条件 & 临界区

当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。导致竞态条件发生的代码区称作临界区。