zoukankan      html  css  js  c++  java
  • 线程安全和不可变性

    竞态之发生在多线程访问相同的资源,同时有一个或多个线程写入东西到资源。相反,如果是多线程读取资源的话,反而不会发生竞态。比如

    public class ImmutableValue {
      
      	private int value = 0;
      
      	public ImmutableValue(int value) {
          	this.value = value;
      	}
      
      	public int getValue() {
          	return this.value;
      	}
    }
    

    一旦 ImmutableValue 实例创建,你就不能改变它的值。ImmutableValue 是不可变的。你能做的只有通过 getValue() 读取它的值。

    如果你要对 ImmutableValue 进行操作,可以通过返回一个新的 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);
      	}
    }
    

    引用不是线程安全的!

    有一点很重要,即使一个对象是不可变、线程安全的,指向对象的引用也许不是线程安全的。比如这个例子

    public class Calculator {
      	private ImmutableValue currentValue = null;
      
      	public ImmutableValue getValue() {
          	return currValue;
      	}
      
      	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 对象,也不是它自己的 ImmutableValue 对象了,因此 Calculator 不是线程安全的。换一种方法来说:ImmutableValue 是线程安全的,但是 ImmutableVlue 的使用不是线程安全的。当尝试通过不可变性实现线程安全时,这点需要牢记。

    要实现 Calculator 线程安全,可以声明 getValue()setValue()add()synchronized

  • 相关阅读:
    索引
    mysql事务
    centos 7 gitlab安装服务器
    内网穿透工具 frp使用
    eslint配置
    nodejs连接mongodb(密码)
    插入排序
    直接插入排序
    koa中 log4js使用
    JS中的prototype、__proto__与constructor(图解)
  • 原文地址:https://www.cnblogs.com/okadanana/p/5898274.html
Copyright © 2011-2022 走看看