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

Java并发编程的艺术

ch1 并发编程的调整

1.1上下文切换

  • 在单核CPU的情况下,也存在上下文切换的概念(时间片)

任务的状态从保存到再加载就是一次切换

  • 在数据量少的情况下,串行有可能比并发编程效率高

使用Lmbench测试上下文切换时长,vmstat统计切换次数

减少上下文切换的方法
  • 无锁并发编程
  • CAS算法(Java的Atomic包)
  • 使用最少线程,避免不必要的创建
实战减少上下文切换
  • jstack命令dump线程信息,查看对应PID的线程在做什么
  • 统计线程分别处于什么状态(onobject-monitor为waiting状态)

若Jboss中有大量线程处于await状态,,可以配置maxThreads的数量。

1.2死锁

避免死锁的几个方法

  • 避免一个线程同时获取多个锁
  • 避免一个线程在锁内同时占用多个资源,尽量保存1:1的关系
  • 尝试使用定时锁(到期释放),lock.tryLock(timeout)
  • 对于数据库锁,加解锁必须在一个连接中。

1.3资源限制

硬件问题:通过“数据ID%机器数”,让对应编号的机器处理数据
软件问题:资源池复用资源,数据库和Socket连接复用。

CH2 Java并发机制的底层实现原理

Java代码编译后变成字节码,由类加载器加载到JVM中,最终转换为汇编在CPU上执行;
CPU常见术语

volatile

  • 保证可见性,不保证原子性
  • synchronized的使用成本低(不引起上下文切换和调度)

处理器不直接和内存通信,而是先将内存数据度到内部缓存,但最终不确定写回到内存的时间。如果声明了volatile,JVM向处理器发送一条前缀为LOCK的指令,讲变量所在缓存行的数据读回到内存。
实现原理为lock指令,(1)将当前处理器缓存行的数据写回系统内存,(2)这个写回内存的操作使在其他CPU里切换了该内存地址的数据无效。(缓存一致性协议:处理器嗅探在总线上传播的数据查看自己所缓存对比看是否过期,如果过期,设置为无效状态。)
Lock前缀指令会引起处理器缓存写回到内存,一个处理器写回到内存会导致其他处理器的缓存无效。

volatile的使用优化

采用追加字节码的方式,配合特点型号的处理器(缓存为64个字节宽,避免头节点和尾节点加载到同一个缓存行,让其在修改时不会互相锁定,当缓存行非64位或者共享变量不会被频繁读写时,不必要将字节码追加至64位(在JDK7中失效,会淘汰和重新排列无用字段,需要使用其他追加字节的方式)。

Synchronized的使用和实现

在1.6中引入偏向锁和轻量级锁,避免获得释放锁造成的消耗。

  • 对于普通方法,锁是当前实例对象
  • 静态同步方法,锁是当前类的Class对象、
  • 同步方法块,是Synchronized括号里配置的对象。
    基于monitorentermonitorexit指令。获得enter时,会尝试获得锁。分别位代码块的开始和方法结束和异常处。
Java对线头

Synchronized锁存在对象头中,若对象为数组类型,使用3个字宽(word),非数组为2word,在32位虚拟中,1字宽=4字节。

  • Java对象头里的Mark Word默认存储对象的Hashcode,分代年龄和锁标记。在运行期间,MW中的数据随着锁标志位的变化而变化。
    ![Java对象头长度.png)
    在这里插入图片描述
锁的升级和对比
  • 无锁状态
  • 偏向锁
  • 轻量级锁
  • 重量级锁
    锁升级过程中只能升级不能降级。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值