进程和线程
进程:一个启动正在运行的程序称之为进程。线程:是操作系统能够进行运算调度的最小单位。它包含在进程中,是进程执行的最小单元,是一个程序的运行轨迹。
一、synchronized
底层实现原理:synchronized 底层字节码文件是通过monitor指令控制线程,同步代码块儿在获取线程的开始部位添加一个monitorrenter指令,在结束部位添加一个monitorexit指令,入下图所示(代码可以通过javap命令编译查看)。为什么最后会有monitorexit命令,是为了防止中间出现异常,而最后能给正常退出,避免造成死锁。
synchronized 是可重入的锁,可重入锁的意思就是,同一个线程进入同步代码块儿是被允许的,并且在父子类之间也是可重入的。底层原理是当线程获取该锁时,计数器加一,再次获得该锁时继续加一,释放锁时,计数器减一,当计数器值为0时,表明该锁未被任何线程所持有,其它线程可以竞争获取锁。
锁优化
在一个线程要想获取锁就需要向系统内核申请资源,在这个过程是非常消耗资源的,应该是为了避免过度的申请消耗,从而在对象做了手脚;一个java对象由对象标记,类型指针,真实数据,内存补齐四部分组成:
对象标记也称Mark Word字段,存储当前对象的一些运行时数据。
类型指针,JVM根据该指针确定该对象是哪个类的实例化对象。
真实数据自然是对象的属性值。
内存补齐,是当数据不是对齐数的整数倍的时候,进行调整,使得对象的整体大小是对齐数的整数倍方便寻址。典型的以空间换时间的思想。
Mark Word
提到锁优化就提到Mark Word,他是用于存储对象自身运行时的数据,如hashcode,GC分代年龄,锁状态标志位,线程持有的锁,偏向线程ID
锁优化的阶段 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁
无锁:就是没有加锁的状态
偏向锁:针对的是锁不存在竞争,每次仅有一个线程来获取该锁,为了提高获取锁的效率,因此将该锁偏向该线程,提升性能。
轻量级锁:偏向锁考虑的是不存在多个线程竞争同一把锁,而轻量级锁考虑的是,多个线程不会在同一时刻来竞争同一把锁。
重量级锁:重量级锁描述同一时刻有多个线程竞争同一把锁。
锁升级过程:
1、首先检查对象头是否为可偏向状态,锁标志是否设置成了1;2、如果对象头是可偏向状态检查线程id是否是自己的线程id,如果是自己的线程id则直接进入同步代码块儿;3、如果不是自己的线程id那么会通过CAS尝试获取锁,这时候成为自旋锁,自旋10次以后如果还没有获取到锁资源,则升级为重量级锁
锁细化:同步代码块儿中存在少量代码,无需枷锁的代码移到同步代码块外面
锁粗花:一个循环中存在加锁操作时,可以将加锁操作提到循环外面执行,一次加锁代替多次加锁,提升性能
来源:https://www.cnblogs.com/btdxqz/p/12560141.html