博客
关于我
多线程系列:线程安全及不可变性
阅读量:100 次
发布时间:2019-02-26

本文共 1686 字,大约阅读时间需要 5 分钟。

当多个线程同时访问同一个资源,并且其中的一个或者多个线程对这个资源进行了写操作,才会产生竞态条件。多个线程同时读同一个资源不会产生竞态条件。

我们可以通过创建不可变的共享对象来保证对象在线程间共享时不会被修改,从而实现线程安全。如下示例:

01 public class ImmutableValue{
02     private int value = 0;
03  
04     public ImmutableValue(int value){
05         this.value = value;
06     }
07  
08     public int getValue(){
09         return this.value;
10     }
11 }

请注意ImmutableValue类的成员变量value是通过构造函数赋值的,并且在类中没有set方法。这意味着一旦ImmutableValue实例被创建,value变量就不能再被修改,这就是不可变性。但你可以通过getValue()方法读取这个变量的值。

如果你需要对ImmutableValue类的实例进行操作,可以通过得到value变量后创建一个新的实例来实现,下面是一个对value变量进行加法操作的示例:

01 public class ImmutableValue{
02     private int value = 0;
03  
04     public ImmutableValue(int value){
05         this.value = value;
06     }
07  
08     public int getValue(){
09         return this.value;
10     }
11  
12     public ImmutableValue add(int valueToAdd){
13         return new ImmutableValue(this.value + valueToAdd);
14     }
15 }

请注意add()方法以加法操作的结果作为一个新的ImmutableValue类实例返回,而不是直接对它自己的value变量进行操作。

引用不是线程安全的!

重要的是要记住,即使一个对象是线程安全的不可变对象,指向这个对象的引用也可能不是线程安全的。看这个例子:

01 public void Calculator{
02     private ImmutableValue currentValue = null;
03  
04     public ImmutableValue getValue(){
05         return currentValue;
06     }
07  
08     public void setValue(ImmutableValue newValue){
09         this.currentValue = newValue;
10     }
11  
12     public void add(int newValue){
13         this.currentValue = this.currentValue.add(newValue);
14     }
15 }

Calculator类持有一个指向ImmutableValue实例的引用。注意,通过setValue()方法和add()方法可能会改变这个引用。因此,即使Calculator类内部使用了一个不可变对象,但Calculator类本身还是可变的,因此Calculator类不是线程安全的。换句话说:ImmutableValue类是线程安全的,但使用它的类不是。当尝试通过不可变性去获得线程安全时,这点是需要牢记的。

要使Calculator类实现线程安全,将getValue()、setValue()和add()方法都声明为同步方法即可。(java会保证对引用的读写是原子的,但add方法中有对currentValue的再次引用,也就相当于i++之类的语法,所以还需要做同步,只有volatile是不行的。)

原文地址:

http://ifeve.com/thread-safety-and-immutability/

转载地址:http://qncy.baihongyu.com/

你可能感兴趣的文章
MySQL InnoDB中意向锁的作用及原理探
查看>>
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>
Mysql InnoDB存储引擎中的checkpoint技术
查看>>
Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
查看>>
MySQL InnoDB引擎的锁机制详解
查看>>
Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
查看>>
mysql InnoDB数据存储引擎 的B+树索引原理
查看>>
mysql innodb通过使用mvcc来实现可重复读
查看>>
mysql interval显示条件值_MySQL INTERVAL关键字可以使用哪些不同的单位值?
查看>>
Mysql join原理
查看>>
mysql order by多个字段排序
查看>>
MySQL Order By实现原理分析和Filesort优化
查看>>
mysql problems
查看>>
mysql replace first,MySQL中处理各种重复的一些方法
查看>>
MySQL replace函数替换字符串语句的用法(mysql字符串替换)
查看>>
Mysql Row_Format 参数讲解
查看>>
mysql select, from ,join ,on ,where groupby,having ,order by limit的执行顺序和书写顺序
查看>>
MySQL Server 5.5安装记录
查看>>
mysql slave 停了_slave 停止。求解决方法
查看>>