====不可变对象定义:====
1,对象创建后其状态不能修改
2,对象所有域都是final的
3,对象时正确创建的,在对象构造期间,this引用没有逸出
====安全发布对象的含义:====
确保使用对象的线程能够看到该对象处于已发布的状态,是对象的状态呈现一致性视图。
安全发布对象的常用模式:
可变对象必须通过安全的方式来发布,通常意味着发布和使用该对象的线程都必须使用同步
一个正确构造的对象可以通过以下方式来安全发布:
* 在静态初始化函数中初始化一个对象引用
* 将对象引用保存到volatile类型域或者AtomicReference对象中
* 将对象引用保存到某个正确构造函数对象的final类型域中
* 将对象引用保存到一个由锁保护的域中,这个常见的就是保存到线程安全的容器中比如Vector或SynchronizedList等等
线程安全的容器类:
1,将一个键/值放入Hashtable、SynchronizedMap、ConcurrentMap中,可安全将它发布给任何从这些容器中访问它的线程。
2,将某个元素放入Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、SynchronizedList、SynchronizedSet中
3,将某个元素放入BlockingQueue、ConcurrentLinkedQueue中
4,其他比如Future和Exchanger等,也能安全发布对象。
通常,要发布一个静态构造的函数,最简单和最安全的做法是使用静态的初始化器,这个在JVM里面有同步保证。
public static Holder holder = new Holder(42);
====事实不可变对象====
如果对象从技术上看是可以变的,但其状态在发布后就不会再改变,那么把这种现象称为事实不可变对象 Effectively Immutable Object。比如要保存每位用户的最近登录时间Date类型,原则上可以修改Date,但业务上初始化后就不会了,那么使用SynchronizedMap就足够了,里面的安全机制可确保Date会被安全的发布。放入后不会改变那就可以了。
对象的发布需求取决于它的可变性:
1,不可变对象可以通过任意机制来发布
2,事实不可变对象必须通过安全方式发布
3,可变对象必须通过安全方式发布,并且必须是线程安全的或者由某个锁保护起来。
在并发程序中使用和共享对象时,可以使用一些实用策略,包括:
线程封闭:
线程封闭的对象只能由一个线程拥有,对象被封闭在该线程中,并且只能由这个线程修改。
只读共享:
在没有额外同步情况下,共享的只读对象可以由多个线程并发访问,但任何线程都不能修改它。包括不可变对象和事实不可变对象。
线程安全共享:
线程安全的对象在其内部实现同步,因此多个线程可以通过对象的公有接口进行访问而不需要进一步的同步。
保护对象:
被保护对象只能通过持有特点锁来访问。保护对象包括封装在其他线程安全对象中的对象,比如SynchronizedMap中的对象,以及已发布的并且由某个特定锁保护的对象。
本人博客已搬家,新地址为:http://yidao620c.github.io/