月泉的博客

什么是竞态条件?什么是数据竞争?

月泉 并发编程

数据竞争是指多个线程同时对内存的同一块数据或者会共同操作的数据(可能不是放在内存中的数据)进行了操作,只要有一个线程对其进行了写操作就会发生数据竞争

竞态条件指的是程序的执行结果是依赖执行线程执行的顺序,其执行过程会出现其它线程执行的顺序的不同而导致执行结果导致偏差,举三个例子:

1.有竞态条件但无数据竞争

//获取库存数量
lock.lock();
int count = getInventory(merchandiseId)
lock.unlock();

//库存大于等于购买
lock.lock();
boolean isBuy = count >= purchaseQuantity;
lock.unlock();
if(isBuy) {
  //生成订单
  lock.lock();
  //库存-1
  lock.unlock();
  //出库......
}else {
  throw new MerchandHungerException("库存不足");
}

以上代码在多线程执行时并不会出现数据竞争,因为不会有多个线程同时对数据进操作,所以对数据的操作都只会有一个线程,但其任然是存在竟态条件的,因为这些共享数据还是会在该线程没有持有锁的情况下会被其它线程修改,导致当前获得的状态是失效的,这种会被线程间执行顺序影响的就是竞态条件

2.有竞态条件有数据竞争

例如一个库存出库系统,商品只有一件了,但同时有2个用户(A用户、B用户)都想要够买这一件商品,于是都加入了购物车都同时点击了结算,代码如下:

//获取库存数量
int count = getInventory(merchandiseId)
//库存大于等于购买
if(count >= purchaseQuantity) {
  //生成订单
  //库存-1
  //出库......
}else {
  throw new MerchandHungerException("库存不足");
}

执行的顺序可能如下 B用户获取的库存,在执行评断的时候其本身获取的数据已经是失效的了,也有可能2个线程间执行的顺序还会更加的不同,这种执行时会受到其它线程间执行的顺序的影响就称为竟态条件

3.无竞态条件有数据竞争

Merchanddis merchanddis = getMerchanddis(merchandiseId);
sychronized(this) {
  //获取库存数量
  int count = getInventory(merchanddis.id);
  //库存大于等于购买
  if(count >= purchaseQuantity) {
	//库存-1
  }else {
	throw new MerchandHungerException("库存不足");
	return;
  }
}
//添加商品已拥有
hadMerchanddis.add(user, merchanddis);
//生成订单
//出库......

上述代码已经不会出现竞态条件因为,不会受到其它线程执行的顺序而导致其自身运行结果的正确性,但其仍然存在数据竞争即hadMerchanddis.add(user, merchanddis);该数据操作还是会被多个线程同时add但当前执行线程不会受到其它线程执行顺序的影响。

竞态条件和数据竞争的区别: 数据竞争主要指的是同一块数据会被多个线程同时操作,被多个线程同时操作时有一个或多个线程写了就是数据竞争。 竟态条件主要指的是当前线程的执行顺序的结果,会被其它线程执行顺序的结果所影响。

月泉
伪文艺中二青年,热爱技术,热爱生活。