• lock中


    fengzhong_yaoye_fengling-007

    悲观锁

    ​ 总是假设最坏的情况,每次去拿数据都会认为别人会修改,所以每次拿数据的时候都会上锁。这样别人拿这个数据就会阻塞直到它拿到共享锁(共享锁每次只给一个线程使用,其他线程阻塞,用完后再把资源转让给其他线程)。传统的关系型数据库里边就用到了很多类似的锁机制,比如行锁,表锁等,读锁,写锁等,都是在操作之前先上锁。Java中Synchronized和ReentrantLock等独占锁j就是悲观锁思想的实现。

    乐观锁

    ​ 总假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但更新的时候会判断一下在此期间别人有没有更新这个数据,可以使用版本号机制和CAS算法实现。

    ​ 乐观锁适用于多读的应用类型,可以提高吞吐量,就像数据库提供的类似write_condition机制,其实都是提供乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的

    分段锁

    ​ 分段锁其实是一种锁的设计,并非具体实现。对于concurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效并发操作

    ​ 并发容器类的加锁机制是基于更小粒度的分段锁,分段锁也是提升多并发程序性能的重要手段之一。

    ​ 在并发程序中,串行操作会降低可伸缩性,并且上下文的切换也会降低性能。在锁上发生竞争时,将同时导致这两种问题,使用独占锁时保护受限资源,基本采用串行方式,每次只能有一个线程访问它。所以对于可伸缩性来说最大的威胁就是独占锁

    一般有三种降低锁的竞争程度的方式:

    1,减少锁的持有时间;2,降低锁的请求频率;3,使用带协调机制的独占锁,这些机制允许更高的并发性。

    在某些情况下,我们可以将锁分解技术进一步扩展为一组独立对象上的锁进行分解,这称为分段锁。

    简单讲解:

    ​ 容器内有多把锁,每把锁用于锁容器中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是concurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问

    举例:

    ​ 在concurrentHashMap中使用一个包含16个锁的数组,每个锁保护散列桶的1/16,其中第N个散列桶由第(N mod 16)个锁来保护。假设使用合适的散列算法使关键字均匀分布,那么这大约能使对锁的请求减少1/16,正是这项技术使concurrentHashMap支持的并发写入达到16个

    xiaochouyu-011

    锁的状态:

    1,无锁状态

    2,偏向锁状态

    3,轻量级锁状态

    4,重量级锁状态

    锁的状态会通过对象监视器在对象头部中的字段表明。

    四种状态会随着竞争的升级而升级,且不可逆,不可降级

    四种锁并非Java语言中的锁,而是jvm为了提高锁的获取与释放效率而做的优化(用Synchronized时

    偏向锁

    ​ 指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价

    轻量级锁

    ​ 当锁是偏向锁时,被另一个线程访问,偏向锁会升级为轻量级锁,其他线程会通过自选形式尝试获取,不会阻塞,提高性能

    重量级锁

    ​ 指当前锁为轻量级锁时,另一个线程虽然自旋,但不会一直持续下去,当达到一定次数还没得到,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低

    参考文章

    你知道Java里有多少种锁吗?(15种锁最全总结)

  • 相关阅读:
    面试常问题
    雷达无线电系列(五)拟合优度检验(matlab)
    LDAP轻量级目录访问协议总结(待完成)
    zipkin数据追踪(待完成)
    git多定制版本管理
    git单修改推送多分支(cherry-pick)
    git工作流及插件使用说明
    基金-股票-期权知识总结(待完成)
    java AESRSA加密解密样例
    分享一个统计文档中不同key的个数的python脚本
  • 原文地址:https://www.cnblogs.com/lifelikeplay/p/16203590.html
Copyright © 2020-2023  润新知