首页 > 代码库 > java并发编程的艺术,读书笔记第三章

java并发编程的艺术,读书笔记第三章

final域的内存语义

写final域的重排规则:禁止把final域的写重排序到构造方法之外,主要包括俩个个方面

1)JMM禁止编译器把final域的写重排序到构造方法之外

2)编译器会在final域写之后,构造函数return之前插入一个storestore屏障,这个屏障禁止处理器把final域的写重排序到构造方法之外

写final域的重排序规则可以确保:在对象引用为任意线程可见之前,对象的final域已经被

正确初始化过了,而普通域不具有这个保障

读final域的重排规则:在一个线程中,初次读对象引用与初次读该对象包含的final域,JMM处理器禁止重排这两个操作。编译器会在读final前插入loadload屏障

读final域的重排序规则可以确保:在读一个对象的final域之前,一定会先读包含这个final

域的对象的引用

对复合final域的重排规则:

在构造函数内对一个final引用对象的成员域内的写入,与随后在构造函数外把这个构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序

双重检查锁定与延迟初始化

基于volatile的解决方案

public class SafeDoubleCheckedLocking {

private volatile static Instance instance;

public static Instance getInstance() {

if (instance == null) {

synchronized (SafeDoubleCheckedLocking.class) {

if (instance == null)

instance = new Instance(); // instance为volatile,现在没问题了

}

}

return instance;

}

}

基于类初始化的解决方案

JVM在类初始化阶段(在class被加载后,且被线程使用前),会执行类的初始化。在执行类的初始化期间,JVM会获取一个锁,这个锁可以同步多个线程对同一个类的初始化。

基于这个特性,可以实现另一种线程安全的延迟初始化方案

public class InstanceFactory {

private static class InstanceHolder {

public static Instance instance = new Instance();

}

public static Instance getInstance() {

return InstanceHolder.instance ;  // 这里将导致InstanceHolder类被初始化

}

}

根据java规范,发生如下情况,会被立即初始化

1)T是一个类,而且一个T类型的实例被创建。

2)T是一个类,且T中声明的一个静态方法被调用。

3)T中声明的一个静态字段被赋值。

4)T中声明的一个静态字段被使用,而且这个字段不是一个常量字段。

5)T是一个顶级类(Top Level Class,见Java语言规范的§7.6),而且一个断言语句嵌套在T

内部被执行。

类初始化的处理过程

类初始化的五个阶段

1) 通过class对象上的同步(获取class对象上的同步锁)       来控制类或者接口的初始化,这个获取锁的线程会一直等待,直到当前线程获取对象的初始化锁

2) 线程执行类a的初始化,同时线程b在对应的初始化锁的condition上等待

3)线程a设置状态位intilized,并呼唤所有condition等待的线程唤醒

4)线程b结束类的初始化

5)线程c执行类的初始化


本文出自 “iter工作总结” 博客,请务必保留此出处http://5855156.blog.51cto.com/5845156/1954184

java并发编程的艺术,读书笔记第三章