首页 > 其他 > 详细

synchronized的实现和锁优化

时间:2020-09-18 23:09:55      阅读:83      评论:0      收藏:0      [点我收藏+]

synchronized的实现和锁优化,
    synchronized实现。
        在同步代码块的前后会生成两条字节码指令,monitorenter,monitorexit。
        当执行monitorenter指令,如果获取到锁对象,那么就将锁的计数器+1,获取不到对象,就会进入阻塞状态。
        当执行monitorexeit指令,将锁的计数器-1,计数器为0的时候,就会释放锁。


    重量级锁:
        线程在获取不到锁的时候,线程就进入阻塞状态,直到锁被释放,线程被唤醒。
        线程阻塞唤醒,这些操作涉及操作系统调用,要从操作系统的用户态切换到内核态。开销大。


    锁优化:
        自旋:
            获取不到锁,在处理器空跑,并询问锁是否被释放。缺点是,浪费cpu资源,进入阻塞的线程获取锁的优先级降低。
            自适应自旋,根据以前获取锁的经历,如果曾经获取到锁,那么自旋时间就短一些,否则时间长一些。
        轻量级锁:
            重量级锁,要不断的在内核态和用户态切换,开销比较大。
            轻量级锁可以避免线程在内核态和用户态中切换,减少性能的开销。(根据使用经验,数据在同步周期内都是不存在数据竞争的)
            实现方法:
                java对象头包含:标记字段(mark word),类型指针。标记字段其中有两位是存储锁标志位。01未锁定,00轻量级锁定,10膨胀重量级锁定,11GC,根据标志位的不同,mark word存储了不同的内容。
                当线程要获取锁的时候,会把锁对象的mark work复制到线程的栈帧中的一个空间(锁记录),
                加锁的时候,jvm会使用CAS将mark word更新为指向锁记录的执行,如果更新成功,则获取锁(mark word标志位更新为00),更新不成功,如果已经是当前线程获取,那么继续执行后续代码,如果当前线程没有持有锁,那么锁就会膨胀为重量级锁(10)。
                解锁的时候, Mark word替换回锁记录数据,如果替换成功,同步过程完成,如果替换不成功,则说明其他线程持有锁,在释放锁的同时,会唤醒其他线程。
        偏向锁:
            就是访问代码块不加锁,直到有其他线程来获取锁,才会对代码块进行加锁。
            当锁对象第一次被线程获取后,会将mark word的标志位设置为01,然后将线程的id,记录在mark word中。持有偏向锁的线程进入同步代码块,不会进行加锁,当有其他线程尝试获取锁,此时就会撤销偏向锁,变成未锁定状态,或者轻量级锁。
           

synchronized的实现和锁优化

原文:https://www.cnblogs.com/haiqichen/p/13693010.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!