线程安全和不变性

竞争条件只有在多个线程正在访问同一资源且一个或多个线程写入资源时才会发生。如果多线程读取相同的资源竞争条件是不会发生的。
我们可以确保线程之间共享的对象永远不会被任何线程更新,那就是让共享对象不可变,从而线程安全。以下一个例子:

public class ImmutableValue{

  private int value = 0;

  public ImmutableValue(int value){
    this.value = value;
  }

  public int getValue(){
    return this.value;
  }
}

注意在构造函数中如何传递ImmutableValue实例的值。还要注意类里面没有setter方法。一旦创建了一个ImmutableValue实例,您将无法更改其值。这是不可变的。然而可以使用getValue()方法读取它。
如果需要对ImmutableValue实例执行操作,可以通过从操作得到的值返回一个新的实例来执行此操作。以下是添加操作的示例:

public class ImmutableValue{

  private int value = 0;

  public ImmutableValue(int value){
    this.value = value;
  }

  public int getValue(){
    return this.value;
  }


      public ImmutableValue add(int valueToAdd){
      return new ImmutableValue(this.value + valueToAdd);
      }

}

注意add()方法如何返回一个新的具有添加操作结果的ImmutableValue实例,而不是将值添加到自身。
引用不是线程安全的
记住!即使一个对象是不可变的,从而线程也是安全的,对该对象的引用可能不是线程安全的,看下面这个例子:

public class Calculator{
  private ImmutableValue currentValue = null;

  public ImmutableValue getValue(){
    return currentValue;
  }

  public void setValue(ImmutableValue newValue){
    this.currentValue = newValue;
  }

  public void add(int newValue){
    this.currentValue = this.currentValue.add(newValue);
  }
}

Calculator类保存对ImmutableValue实例的引用。注意可以通过setValue()和add()方法来更改引用。因此,即使Calculator类在内部使用不可变对象,它本身也不可变,但也不是线程安全的。换句话说:ImmutableValue类是线程安全的,但使用它的不是。当尝试通过不变性实现线程安全性时,这是要记住的。
为了使计算器类线程安全,您可以声明getValue(),setValue()和add()方法synchronized。那会做到这一点。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值