0
点赞
收藏
分享

微信扫一扫

synchronized实现原理

有点d伤 2023-08-23 阅读 37

特性

开始时是乐观锁,如果加锁操作频繁就会转换成悲观锁

开始时是轻量级锁,如果锁被占用的时间很长,就会装换成重量级锁.

轻量级锁的实现是使用自旋锁策略

不是一个公平锁 ,

是一个可重入锁,

不是一个读写锁


加锁过程

jvm 将 synchronized 分为四个状态 无锁 , 偏向锁, 自旋锁 , 重量级锁

偏向锁

偏向锁不是立即加锁, 而是在锁的对象头中进行标记 来判断当前的锁是属于哪一个线程,

如果没有其他的线程来参与锁竞争,就不会真正的进行加锁操作,从而降低程序开销,如果有其它的线程来参与锁竞争,就会取消偏向锁状态,进入轻量级锁状态

轻量级锁

随着其他的线程参与锁竞争,synchronized 取消偏向锁的状态,进入轻量级锁的状态----> 自适应的自旋锁 通过CAS实现的

通过CAS检查并实现更新一块内存

如果更新成功, 就认为加锁成功

如果更新失败就认为加锁失败,进入自旋锁,而当自旋的时间或次数到达一定时,就会停止自旋操作这就是所谓的自适应

重量级锁

随着线程竞争进一步激烈,自旋锁不能快速获取到锁的状态,就会膨胀成重量级锁 

此处的重量级锁会使用到内核的mutex(互斥锁)

当执行加锁操作时,会进入到内核态,在内核态中判断锁是否被占用,如果没有被占用,就加锁成功,切换回用户态; 如果锁被占用,就会加锁失败,此时线程进入锁的等待队列,挂起,等待被操作系统唤醒, 直到锁被释放,操作系统才唤醒该线程,尝试重新获取锁

其他的优化操作

锁消除

编译器和JVM判断锁是否可以被消除

例如 StringBuffer 创建这个实例,进行append 字符拼接操作,会进行加锁和解锁, 而在单线程中,这并不需要进行加锁解锁操作,此编译器和JVM就会进行锁消除优化操作,防止频繁的加锁解锁,造成资源的浪费

锁粗化

如果一段逻辑当中出现多次的加锁解锁操作,编译器和JVM就会进行锁粗化,锁的粒度分为粗和细,实际开发中使用的细粒度锁,期望释放锁让其它的线程来使用这个锁,但可能实际上并没有其他的线程来使用这个锁,此时JVM就会自动实现锁粗化,避免锁的频繁申请和释放


举报

相关推荐

0 条评论