并发变成学习三(对象的共享)


1.可见性:为了确保多个线程之间的内存写入操作的可见性,必须使用同步机制。在没有使用同步的情况下,编译器,处理器以及运行时等都有可能对操作的执行顺序进行一些意想不到的调整。

2.加锁可见性: a,内置锁可以用于确保某个线程以一种可预见的方式来查看另外一个线程的执行结果。
      b,java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程,当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。

3,线程封闭:当访问共享的可变数据时,通常需要使用同步,一种避免使用同步的方式就是不共享数据。如果仅在单线程内访问数据,就不需要使用同步,这种技术称为线程封闭。

ThreadLocal: ThreadLocal对象通常用于防止对可变的单实例变量(Singleleton)或全局变量进行共享。

4.不可变对象一定是线程安全的。不可变性并不等于将对象中的所有的域都申明为final类型,这个对象仍然是可变的。因为在final类型的域中可保存对可变对象的引用。

5.当满足以下条件时,对象才是不可变的:
    对象创建以后其状态就不能改变
    对象的所有域都是final类型
    对象是正确创建的(在对象创建期间,this引用没有逸出)

6.任何线程都可以在不需要额外同步的情况下安全的访问不可变对象,即使在发布这些对象时没有使用同步。

7.安全发布的常用模式:可变对象必须通过安全的方式发布,这通常都意味着在发布和使用该对象的线程时都必须使用同步。
要安全的发布一个对象,对象的引用以及对象的状态必须同时对其他线程可见,一个正确构造的对象可以通过以下方式来安全发布。
   a,在静态初始化函数中初始化一个对象引用
   b,将对象的引用保存在volatile类型或者AtomicReferance对象中
   c,将对象的引用保存到某个正确构造对象的final类型域中
   d,将对象的引用保存到一个由锁保护的域中
常用的线程安全集合:HashTable,SynchronizedMap,ConcurrentMap,Vector,CopyONWriteArrayList,CopyOnWriteArrayList,SynchronizedList,SynchronizedSet,BlockingQueue,ConcurrentLinkedQueue
将某个元素加入到这些集合中,则可以将该元素安全发布到任何访问这些元素的线程中。

8.通常要发布一个静态构造的对象,最简和最安全的方式是使用静态的初始化器。
eg:public static Holder holder = new  Holder(42);
静态初始化器由JVM在类的初始化阶段执行,由于在JVM内部存在着同步机制,因此通过这种方式初始化的任何对象都可以安全发布。











猜你喜欢

转载自annybz.iteye.com/blog/1956740