JUC
1.进程线程 同步异步 并发并行
线程创建的三种方式
linux查看进程中的线程命令
top -H -p PID(进程id)
java jps命令
jstack PID (详细快照)
远程使用jconsole连接服务
java -Djava.rmi.server.hostname=172.19.71.34
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=端口号
-Dcom.sun.management.jmxremote.ssl=fasle(是否安全链接)
-Dcom.sun.management.jmxremote.authenticate=false(是否认证)类名
栈与栈帧
Java 线程6种状态
并发临界区
synchronized使用对象锁保证了临界区代码的原子性
Synchornized 在普通方法上锁的this对象
Synchornized 在静态方法上锁的class对象
private 和final 保证线程安全 开闭原则
多个线程调用同一个实例是线程安全的,每一个方法的操作是线程安全的,但是方法的组合不是线程安全的
超买超卖问题,转账问题 对synchronized(this/Class.class)
2.monitor
偏向锁 JDK6
第一次CAS获取到锁monitor时,将线程threadID 记录到markword头, 之后比较线程ID来进行是否需要CAS。
JOL 查看对象的偏向锁标记 MarkWord 头 001
启动开启偏向锁命令参数
-XX:BiasedLockingStartupDelay=0
禁用偏向锁
-XX:-UseBiasedLocking
存在锁竞争 时锁膨胀升级
启用偏向锁
-XX:+UseBiasedLocking
调用hashcode 会使对象从偏向为普通状态
为什么轻量级和重量级调hashcode()不会变为普通状态?
因为轻量级锁 hashcode存放在栈帧lockRecord中 重量级锁的hashcode在monitor中
wait notify
批量锁偏向 jvm 阈值20次 撤销偏向超过20次 不会升级到轻量级锁 而是取消偏向之前的线程,重新偏向与另一个线程。
jvm 阈值40次 撤销偏向超过40次之后,对象不偏向于任何线程。
锁消除
jvm 默认开启 JIT对没有竞争的代码进行消除 synchronized
轻量级锁
栈帧LockRecord 对象
CAS成功 替换markword 00
锁重入 CAS LockRecord 计数+1 尝试替换Markword 每次都会CAS
CAS 失败原因 线程竞争激烈 ,流程 thread-01把Object的monitor升级为重量级锁 并进入monitor的阻塞list中
CAS失败 锁膨胀 通过monitor找到地址并把owner置位null 唤醒阻塞list
重量级锁
自旋优化 JDK7以后由JVM控制
Sleep 、Wait
Thread 和Object
Sleep不会
锁 Wait会释放锁 进入WaitSet
wait+synchronized
thread state time_wait
JDK Thread Join( ) 保护性暂停模式
死锁
volatile 保证可见性和有序性 保证不了原子性