首页 > 编程语言 > 详细

java并发编程读书笔记(1)

时间:2016-03-03 19:06:35      阅读:182      评论:0      收藏:0      [点我收藏+]

1. 一些原则

  1. RIM(Remote Method Invocation):远程方法调用
  2. Race Condition:竞态条件
  3. Servlet要满足多个线程的调用,必须是线程安全的
  4. 远程对象,即通过远程方法调用将对象放入字节流中传给其他jvm的对象,要特别注意对象中的共享状态
  5. Shared:共享的
  6. Mutable:可变的
  7. 当设计线程安全的类时,良好的面向对象技术、不可修改性,以及明晰的不变性规范都能起到一定的帮助作用;
  8. 无状态对象是线程安全的:没有任何域也不包含任何对其他类中域的引用(比如StatelessFactory implements Servlet),多个线程访问并没有共享状态,不会影响其正确性。
  9. 最常见的一个静态类型是:先检查后执行(Check-Then-Act)操作,即通过一个可能失效的观测结果来决定下一步的动作。
  10. 要保持状态的一致性,就需要自单个原子操作中更新所有相关的状态变量
  11. 内置锁(Intrinsic Lock),监视锁(Monitor Lock):每个对象都可以当做。
  12. 重入:当某个线程请求一个由其他线程持有的锁时会被阻塞,但请求他自己持有的锁就会成功。内置锁是可重入锁。
  13. 子类继承了父类,重写了父类的synchronized方法,访问子类的这个方法时要先获得父类的锁,然后获取自身的锁。如果在这个方法里又调用了父类的这个方法(super.xx),可以继续说明,获取的父类锁可以重入。
  14. 对于每个包含多个变量的不变条件,其中涉及的多有变量都需要由同一个锁来保护
  15. java内存模型要求变量的读取操作和写入操作都必须是原子操作,但对于非volatile类型的64位数值变量(double,long),jvm允许将64位的读操作或写操作分解为两个32位的操作。当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高32位和另一个值的低32位。因此,即使不考虑失效数据问题,在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,除非使用volatile来声明他们或者用锁保护起来。
  16. 加锁的含义不仅仅局限于互斥行为,还包括内存可见性。为了确保所有的线程都能看到共享变量的最新值,所有的执行读操作或写操作的线程都必须在同一个锁上同步。
  17. 把变量声明为volatile类型后,编译与运行时都会注意到这个变量是共享的,因此不会讲该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存到寄存器或者对其他处理器不可见的地方,因此在读取volatile变量时总会返回最新写入的值。
  18. volatile的一个用法:while的条件变量,为保证可见性。
  19. 加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。
  20. 发布(Publish)一个对象:是对象能够在当前作用域之外的代码中使用。
  21. 逸出(Escape):当某个不应发布的对象被发布时。

2. 对象的共享

2.1 volatile确保可见性

java内存模型要求变量的读取操作和写入操作都必须是原子操作,但对于非volatile类型的64位数值变量(double,long),jvm允许将64位的读操作或写操作分解为两个32位的操作。当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高32位和另一个值的低32位。因此,即使不考虑失效数据问题,在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,除非使用volatile来声明他们或者用锁保护起来。

加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。

把变量声明为volatile类型后,编译与运行时都会注意到这个变量是共享的,因此不会讲该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存到寄存器或者对其他处理器不可见的地方,因此在读取volatile变量时总会返回最新写入的值。

2.2 volatile可见性的应用

  • 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。
  • 该变量不会与其他状态变量一起纳入不变性条件中
  • 在访问变量时不需要加锁

比如,while循环的条件变量,如果监视是否改变,需要设置为volatile

volatile boolean asleep;
...
   while(!asleep)
          countSomeSheep();

  2.3发布与逸出

发布(Publish)一个对象是指:使对象能够在当前作用域之外的代码中使用。

在许多情况,我们要确保对象及其内部状态不被发布。而在某些情况,我又需要发布该对象,但如果在发布时要确保线程安全性,则可能需要同步。发布内部状态可能会破坏封装性,使线程难以维持不变的状态。例如,如果在对象构造完成之前就发布该对象,就会破坏线程安全性。

发布对象的最简单的方法是将对象的引用保存到一个共有的静态变量中。

逸出(Escape):当某个不应该发布的对象呗发布时。

程序list 3-6
class UnsafeStates{ private String[] states = new String[]{"as","dsf",...}; public String[] getStates(){return states;} }

  如果按上述的方式发布states,则任何调用者都可以修改数组,这是不安全的。

 

 

 

 

 

 

 

 

 

 

 

java并发编程读书笔记(1)

原文:http://www.cnblogs.com/woshimrf/p/5238827.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!