《Java并发编程艺术》读书笔记

1. 多线程并不一定比串行任务省时

原因是多线程存在上下文切换问题,需要时间

2. 避免死锁的方法

死锁产生的四大要素
资源占有
且不释放
资源不可抢占
资源的互斥
存在循环引用

3. 避免死锁(银行家算法)

避免一个线程同时占有多个锁
避免一个锁内占用多个资源
尝试使用定时超时锁,lock.tryLocal(timeOut)
数据库锁,获取锁和释放锁必须在同一个数据库连接中

4. 同步的实现原理

锁总线
锁内存

5. Synchronized实现原理

jvm的monitor进入或exit
monitorEnter进入同步块 monitorExit退出同步块 每个对象都有Monitor
java对象头里面保存了锁信息(年龄代、hashcode)

6. 锁的升级

无锁状态
偏向锁
轻量锁
重量锁

7. CAS实现

  1. 空转自旋
  2. 底层实现:CMPXCHG指令
  3. Atomic包里面的:AtomicInteger、AtomicBoolean、AtomicLong、AtomicIntegerArray、AtomicReference、LongAdder、DoubleAdder等
    CAS的缺陷 :
  1. CPU自旋空转,浪费资源和时间
  2. ABA问题:

使用版本号解决ABA问题
AtomicStampedReference解决ABA问题

  1. 只能实现一个共享变量的原子性,如果需要保证多个共享变量的原子性,需要使用AtomicReference

8. Java内存模型

  • 线程之间的通信

    共享内存
    消息传递机制

  • 主存-----》线程的本地工作内存(共享变量的副本)
  • 保证内存可见性,禁止指令重排序,使用内存屏障来实现禁止指令重排序

    编译器优化重排序
    指令级并行重排序
    内存系统重排序

  • CPU的读写缓冲区造成不同步,造成了读写的重排序
  • 内存屏障分类

    loadLoad屏障
    loadStore屏障
    StoreStore屏障
    SoreLoad屏障(保证共享变量的可见性)

  • 指令重排,不会对单线程的数据依赖操作做出重新排序 as-if-serial
  • double和long的读写不具有原子性

    因为二者是64位,会分成两个32位的事务操作

  • volatile

    可见性
    读写的原子性,double和long的64位也可以保证读写的原子性。
    但不能保证(自增自减等操作)操作的原子性

8. Reentrant可冲入锁

使用AQS实现
AQS持有一个volatile的state来实现同步
加锁的调用步骤

Reentrant.lock()
FairSync.lock()
AbstractQueueSynchronizer.acquire()
ReentrantLock.tryAcquire()

ReentrantLock

公平锁,获取时,先获取volatile修饰的state变量
非公平锁,获取是,先更新volatile修饰的state变量
在这里插入图片描述

9. final域保证在构造方法里面已经完成初始化,不会指令重排在构造方法之外
多线程读一个final域,一定会先读对象的引用

10. doubelCheck方案是保证在初始化的时候,初始化不会被指令重排序,从而影响到判空操作。防止访问到一个非空,但未初始化的对象。
11. 静态内部类实现单例

原理是:类的初始化会加锁(初始化锁)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值