文章目录
一、线程安全和不变性
竞争条件只发生在多个线程同时访问相同资源,并且存在一个或多个线程修改了共享资源,如果多个线程只读共享资源那么不会产生竞争条件。
下面我们通过一个实例来说明当一个共享资源被多个线程访问,但没有线程修改共享资源时不会产生竞争条件。
public class ImmutableValue{
private int value = 0;
public ImmutableValue(int value){
this.value = value;
}
public int getValue(){
return this.value;
}
}
请注意 ImmutableValue 提供了一个传入指定 value 的构造函数,一旦对象被创建,该对象没有提供任何修改value值的方法,所以value的值无法被修改。
特别注意:对象引用不是线程安全的
需要注意的是,当一个对象不可变时对象本身是线程安全的,但是对象的引用可能不是线程安全的。举例:
public class Calculator{
private ImmutableValue currentValue = null;
public ImmutableValue getImmutableValue(){
return currentValue;
}
public void setImmutableValue(ImmutableValue newValue){
this.currentValue = newValue;
}
public void add(int newValue){
this.currentValue = new ImmutableValue(currentValue.getValue() + newValue);
}
}
Calculator 类引用了一个 ImmutableValue 对象,请注意它可以通过 setImmutableValue() 方法和 add() 方法改变了 ImmutableValue 对象的引用。换句话说,即使 ImmutableValue 对象是不可变的,但它也是非线程安全的。ImmutableValue 类是线程安全的,但对象的引用是非线程安全的。所以特别注意:对象的引用可能是非线程安全的。 可以通过给 setImmutableValue() 方法和 add() 方法加锁(使用 synchronized 关键字等)保证线程安全。