目录
目标
锁是访问资源的凭据,会消耗资源。
wait会破会Synchronized的原子性,因为会释放锁。
Synchronized从使用到原理。
JAVA中锁的概念
冲突:指数据的不一致性。
自旋锁:CAS操作机制,循环尝试等待。
乐观锁:认为不会有冲突竞争情况,会进行比对判断,不一致则失败。CAS机制。
悲观锁:认为一直会冲突竞争情况,每次只有一个线程可以拿到锁。
独享锁:在同一时刻只会有一个线程拿到,互斥。
共享锁:在同一时刻可以被多个线程获取。
可重入锁、不可重入锁:线程拿到锁后,如果没有释放,可以再次获取该锁,则为可重入,同一个线程可以重复加锁,否则为不可重入会进入阻塞状态。平常使用的锁基本都是可重入锁。
公平锁、非公平锁:严格保证先来后到的顺序获取锁,则为公平锁,能插队则为非公平锁。
同步关键字synchronized
实例方法:作用于当前类实例。
静态方法:作用当前类对象。
锁消除:单个线程频繁使用synchronized进行加锁和解锁,则会进行jit优化,消除了锁。例如:StringBuffer。
锁粗化:
synchronized底层原理
堆内存中的java对象
-
java对象在内存中的布局
堆中存储的实例对象,只会存储实例字段的值和对象头相关的元数据信息。
padding为补齐占位符。
静态字段、方法、相关代码、静态方法等类的结构信息(类的所有信息都是元数据)都存储在方法区中。 -
对象头部
Array length:存储的是数组对象的长度。
Mark Word:实际上是对象当中,对象头部的一小段内存区域,存 储的值,主要包含5种属性。
- 如果对象未锁定,将状态拷贝到栈帧中的lock record中,通过CAS操作赋新值,即抢锁,修改成功后即抢锁成功,改为轻量级锁。
- 多个线程通过CAS抢锁,失败则会自旋,尝试次数过多就会升级成重量级锁(用到了另外一个对象Object monitor)。
对象监视器(管程):每个对象都会有一个对象监视器,抢锁成功后owner指向对应的线程。entryList存储抢锁失败的线程,其中的线程状态为blocked状态,避免频繁消耗cpu资源,此时对象头中的mark word的值变成重量级锁,其引用指向Object monitor对象。
objectmonitor
waitset:wait方法在synchronized方法中执行,进入到waitset中,线程状态为waiting,同时将锁释放。
wait/notify在synchronized关键字中的情况。
- 如果对象未锁定,将状态拷贝到栈帧中的lock record中,通过CAS操作赋新值,即抢锁,修改成功后即抢锁成功,改为轻量级锁。
-
偏向锁
概念理解:减少CAS资源的损耗,只有一个线程抢锁,存储的线程如果是当前线程则不需要抢锁,直接获取该锁,则为偏向锁,若是其它线程,则升级为轻量级锁。
- 锁的升级过程
只有锁升级,没有锁降级。
- 锁的升级过程