Java并发编程(Java Concurrency)(10)- 线程安全与不变性(Thread Safety and Immutability)
2016-11-19 08:14
441 查看
原文链接:http://tutorials.jenkov.com/java-concurrency/thread-safety-and-immutability.html
摘要:这是翻译自一个大概30个小节的关于Java并发编程的入门级教程,原作者Jakob Jenkov,译者Zhenning Lang,转载请注明出处,thanks and have a good time here~~~(希望自己不要留坑)
竞争只发生在多个线程写相同资源的时候,如果仅仅是多个线程读取同一个资源,则不会发生竞争。
那么可以通过使共享对象保持不变(immutable)来让使用它的线程无法更新这个对象,从而达到线程安全,例如:
上例中在构造函数中给 value 赋值,而由于没有 setter 方法,value 的值也无法被改变。一旦 ImmutableValue 的实例被创建,其 value 就保持不变,我们称之为具有不变性。
如果需要对 ImmutableValue 的实例进行一些操作,那么可以通过返回一个具有操作后结果的新的实例来实现不变性,下例展示了 add 操作是如何保持不变性的:
请仔细分析 add() 方法是如何通过返回一个新的 ImmutableValue 实例保持不变性的。
Calculator 类包含一个 ImmutableValue 实例的引用。如果仔细分析 setValue() 和 add() 方法,我们可以发现虽然 ImmutableValue 类本身是具有不变性的,但 Calculator 类却不具有不变性,也并非线程安全的。换言之,虽然具有不变性的类本身是线程安全,但对其引用的使用却不一定是线程安全的。这是想通过不变性达到线程安全目的所需要牢记的事。
为了使 Calculator 类变得线程俺去,可以将 getValue(), setValue(), 和 add() 方法声明成同步的(synchronized)。
摘要:这是翻译自一个大概30个小节的关于Java并发编程的入门级教程,原作者Jakob Jenkov,译者Zhenning Lang,转载请注明出处,thanks and have a good time here~~~(希望自己不要留坑)
竞争只发生在多个线程写相同资源的时候,如果仅仅是多个线程读取同一个资源,则不会发生竞争。
那么可以通过使共享对象保持不变(immutable)来让使用它的线程无法更新这个对象,从而达到线程安全,例如:
public class ImmutableValue{ private int value = 0; public ImmutableValue(int value){ this.value = value; } public int getValue(){ return this.value; } }
上例中在构造函数中给 value 赋值,而由于没有 setter 方法,value 的值也无法被改变。一旦 ImmutableValue 的实例被创建,其 value 就保持不变,我们称之为具有不变性。
如果需要对 ImmutableValue 的实例进行一些操作,那么可以通过返回一个具有操作后结果的新的实例来实现不变性,下例展示了 add 操作是如何保持不变性的:
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 实例保持不变性的。
实例的引用是不安全的(The Reference is not Thread Safe)!
非常值得注意的一点是,即便一个对象本身是具有不变性并且线程安全的,对这个对象的引用可能并不是线程安全的。例如: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() 方法,我们可以发现虽然 ImmutableValue 类本身是具有不变性的,但 Calculator 类却不具有不变性,也并非线程安全的。换言之,虽然具有不变性的类本身是线程安全,但对其引用的使用却不一定是线程安全的。这是想通过不变性达到线程安全目的所需要牢记的事。
为了使 Calculator 类变得线程俺去,可以将 getValue(), setValue(), 和 add() 方法声明成同步的(synchronized)。
相关文章推荐
- Java并发编程(Java Concurrency)(9)- 线程安全与共享资源(Thread Safety and Shared Resources)
- 线程安全和不可变性(Thread Safety and Immutability)
- The Java™ Tutorials — Concurrency :Defining and Starting a Thread 线程的定义和启动
- 10、Java并发性和多线程-线程安全与不可变性
- ACE线程安全与同步(Thread Safety and Synchronization)
- 《Java Concurrency in Practice》 学习笔记--第二章:线程安全
- 转:FreeLibraryAndExitThread DLL中线程的安全退出
- Java并发编程(二)--java线程安全的一些基础
- Java并发编程(Java Concurrency)(8)- 竞争与临界区(Race Conditions and Critical Sections)
- FreeLibraryAndExitThread DLL中线程的安全退出
- java并发编程:线程安全管理类--原子包--java.util.concurrent.atomic
- java线程研究---(10)Thread同步:死锁
- 转:FreeLibraryAndExitThread DLL中线程的安全退出
- 【java线程安全及不可变性】
- Java并发编程(Java Concurrency)(5) - 同一线程(Same-threading)
- java线程安全的ThreadLocal
- Java Thread&Concurrency(10): 深入理解ThreadLocal及其实现原理
- JAVA Final KeyWord And Thread Safety
- 【java线程安全及不可变性】
- Java并发编程(Java Concurrency)(7)- 创建并启动 Java 线程