0%

重新认识“锁”这个字

2020年5月22日 下午4:19

重新认识“锁”这个字:这点非常非常重要

  1. x锁 == 争抢锁的x规则:
    1. 我们这里涉及到悲观锁、乐观锁、自旋锁、适应性自旋锁、无锁、偏向锁、轻量级锁、重量级锁、公平锁、非公平锁、可重入锁、不可重入锁、共享锁、排他锁这十几种锁
    2. 什么什么锁,翻译过来就是:我们目前按什么什么规则进行争抢锁

锁知识的系统讲解与分类

不可不说的Java“锁”事 - 美团技术团队

synchronized锁的原理:这个问题要专门拉出来讲,考的人太多

  1. 涉及到的数据结构:
    1. 对象头中的:Mark Word(标记字段)Klass Pointer(类型指针)
    2. Monitor:
      1. Monitor可以理解为一个同步工具或一种同步机制。说白了就是synchronized是调用Monitor实现的
      2. synchronized通过Monitor来实现线程同步,Monitor是依赖于底层的操作系统的Mutex Lock(互斥锁)来实现的线程同步
  2. synchronized最初实现同步的方式
    1. 阻塞或唤醒一个Java线程需要操作系统切换CPU状态来完成,这种状态转换需要耗费处理器时间。如果同步代码块中的内容过于简单,状态转换消耗的时间有可能比用户代码执行的时间还要长

最最关键、基础的两种锁:

  1. 【极端】大家来抢,但只有一个人获得操作对象,不论这个人对这个对象进行何种操作,别人都无法获得这个对象,看看都不行
  2. 【平和】大家都可以来看到这个对象,但是有一点需要大家保证:你看看可以,一旦你想改这个对象,你必须满足一定的要求:
    1. 这里面又设计了两种场景需求
      1. 面试必备之乐观锁与悲观锁 - 掘金
      2. 外加数据的版本号手段:
        1. 在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功
      3. 不加版本号,直接根据数据值本身是否变更:
        1. CAS:compare and swap(比较与交换)
        2. 但是:
          1. 会导致ABA 问题,解决ABA我们又要使用版本号
          2. 循环时间长开销大
            1. 自旋CAS(也就是不成功就一直循环执行直到成功)如果长时间不成功,会给CPU带来非常大的执行开销。
          3. 只能保证一个共享变量的原子操作
            1. CAS 只对单个共享变量有效,当操作涉及跨多个共享变量时 CAS 无效
  3. 上面是从人话的角度去切入真实的场景,计算机只不过在模拟我们日常的需求而已。但是,如果我们专业一点说的话:
    1. 极端 ==> 悲观锁
    2. 平和 ==> 乐观锁
  4. 当我们需要在多线程下保护一个对象时,我们如何选择保护它的模式?
    1. 这个可以理解成第三方保镖公司,这个公司有自己的套餐服务,你可以选择你保护的这个人的等级:有皇家护卫队等级,有退役海报突击队等级,有配枪的不配枪的….
    2. 这就等同于上面所说的极端、平和等等模式,不同的人我们选择不同的保护等级,保护领导人当然直接上皇家护卫队等级等级,保护你个平民当然随便请个健身教练就行了,这里强调的是适合!
    3. 这就涉及到乐观锁和悲观锁的使用场景:
      1. 具体来说:CAS与synchronized的使用情景
      2. 简单的来说CAS适用于写比较少的情况下(多读场景,冲突一般较少),synchronized适用于写比较多的情况下(多写场景,冲突一般较多)