《java并发编程实战》基础知识——1

第一部分 基础知识

第二章 线程安全性

1.java中的主要同步机制是关键字synchronized,它提供了一种独占的加锁方式,但“同步”这个术语还包括volatile类型的变量,显示锁(Explicit Lock)以及原子变量。

2.如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么程序就会出现错误。有三种方式可以修复这个问题:

  • 不在线程之间共享该状态变量
  • 将状态变量修改为不可变的变量
  • 在访问状态变量时使用同步

3.竞态条件(Race Condition)

由于不恰当的执行时序而出现不正确的结果是一种非常重要的情况,它有一个正式的名字:竞态条件。

当某个计算的正确性取决于多个线程的交替执行时序时,就会发生竞态条件。换句话说,就是正确的结果要取决于运气。最常见的竞态条件类型就是“先检查后执行(Check-Then-Act)”操作,即通过一个可能失效的观测结果来决定下一步的动作。

例如:延迟初始化的竞态条件

@NotThreadSafe
public class LazyInitRace {
	
	private Object instance=null;
	public Object getInstance(){
		if(instance==null){
			instance = new Object();
		}
		return instance;
	}
}

假定线程a和线程b同时执行getInstance(),线程a看到instance为空,创建了一个新的Object对象,此时线程b也需要判断instance是否为空,此时的instance是否为空取决于不可预测的时序:包括线程a创建Object对象需要多长时间以及线程的调度方式,如果b检测时,instance为空,那么b也会创建一个instance对象。

竞态条件的另一种情况:在“读取-修改-写入”这种操作(例如递增一个计数器)中,基于对象之前的状态来定义对象状态的转换。

例如:

public class UnsafeSequence {
	private int value;
	
	/**返回一个唯一的数值*/
	public int getNext(){
		return value++;
	}
}

UnsafeSequence的问题在于,如果执行时机不对,那么两个线程在调用getNext时会得到相同的值。

竞态条件并不总是会产生错误,还需要某种不恰当的执行时序。

猜你喜欢

转载自blog.csdn.net/OliverQY/article/details/80796863