代码改变世界

并发编程实战1-chap1-2-斗者6星

2019-04-08 14:30  剑动情缥缈  阅读(184)  评论(0编辑  收藏  举报

一、线程安全性

  1.线程安全关注点:对共享的和可变的状态的访问

  2.JAVA同步机制:synchronized、volatile、显示锁、原子变量

  3.无状态对象一定是线程安全的:不包含任何域,也不包含任何对其他类中域的引用,计算过程中的临时状态仅存在于线程栈上的局部变量,并且只能由正在执行的线程访问

  4.竞态条件本质:基于一种可能失效的结果做出判断或者执行某个计算,如先检查后执行、延迟初始化

  5.java.util.concurrent包中原子变量类

  6.要保持状态一致性:需要在单个原子操作中,更新所有相关的状态变量

  7.重入:取锁的操作粒度是线程,而不是调用,意味着同一个线程可以获得由自己持有的锁,可以避免子类方法调用基类方法执行中的死锁

  8.如果用同步来协调对某个变量的访问,那么在访问这个变量的所有位置都需要使用同步;当使用锁来协调对某个变量的访问时,在访问变量的所有位置都要使用同一个锁。

  9.对于每个包含多个变量的不变性条件,其中涉及的所有变量都需要由同一个锁来保护。

  10.即使类的每个操作均保证了原子性,但是将多个操作合并为一个复合操作,还是需要额外的加锁机制

  11.对方法使用synchronized会比较重载,可以选择对可能存在竞态条件的代码块使用synchronized关键字

二、对象的共享

  1.同步代码块的两层语义

  • 可以确保以原子的方式执行操作
  • 保证内存可见性,即当一个线程修改了对象状态后,其他线程能看到发生的状态变化,如果某线程修改了共享变量,如果未使用正确的同步,其他线程很可能看不到状态变化

  2.get和set方法均需要使用同步,虽然get方法不会修改共享变量的值,但是可以保证可见性

  3.最低安全性:能看到变量值为之前某个线程设置的值,而不是随机值

  4.volatile变量:会直接操作主内存,而非工作内存,访问volatile变量不会加锁,也就不会使线程阻塞,因此比synchronized更轻量级

  • 编译器与运行时都会注意到这个变量是共享的,因此不会将变量上的操作与其他内存操作一起重排序
  • volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量总会返回最新写入的值
  • 写入volatile变量相当于退出同步代码块,读取volatile变量相当于进入同步代码块
  • volatile变量无法保证++操作的原子性,所以具体操作仍然要使用同步,原子变量可以提供”读-改-写“的原子操作

  5.发布:使对象能够在当前作用域之外的代码中使用,发布一个对象时,该对象的非私有域中的引用的所有对象同样会被发布。

  6.逸出:当某个不应该发布的对象被发布时

  7.线程封闭:仅在单线程内访问数据,就不需要同步,如JDBC连接池的使用

  1)Ad-hoc线程封闭:维护线程封闭的职责完全由程序实现来承担