有资源共享的地方就有竞争条件,有竞争条件就有线程安全,有线程安全就有线程同步,有线程同步就有锁。🔒 🔒

谈谈类型

有时候让我们对一个东西去做总结的时候其实挺乱的,因为不知道从什么维度去进行总结,又因为不知道从哪里去总结,所以随意总结了一下,导致重点归纳不到位。也许在不同的维度上,自己都有一个比较好的认知,但是却不能表述出来。这种能力是我比较稀缺的。

这种随意的总结偶尔会造成一个恶劣的后果,就是在给他们展示成果的时候,因为总结不到位,导致观众或者是评委看不到作品的全貌。一份随意的也不能够从多方面在展示的成果,只能是记流水账一样。因此,在总结的时候一定要从各个维度出发,针对这些维度它的表现形式是怎样的,是如何工作的,又达到了什么样的效果。

锁的类型

认知

如果对锁的应用维度不够了解,我们好像不能说出锁的啥类型,锁,不就是用来避免竞争条件,同步执行的么,还有啥类型么。

类型

  • 锁住同步资源
  • 🔒锁住—-> 悲观锁
  • 不锁住 —-> 乐观锁
  • 锁住同步资源失败,要不要阻塞
  • 阻塞
  • 不阻塞
  • 自旋锁
  • 适应性自旋锁
  • 多线程竞争锁是否需要排队
  • 需要—-> 公平锁
  • 不需要-> 非公平锁 (先尝试,失败在排队)
  • 一个线程是否可以多次获取同一把锁
  • 能 —-> 可重入锁
  • 不能—> 不可重入锁
  • 多线程能否共享锁
  • 能 —-> 共享锁
  • [ ] 不能—> 排它锁

    乐观和悲观

    这两锁就是心态上的区别(读写量的区别)

  • 悲观锁: 需要显示的调用 lock.locklock.unlockSynchronizer 除外

    • Lock的实现
    • Synchronizer
  • 乐观锁

    • CAS
      • ABA问题
      • 长时间自旋带来的CPU消耗问题
    • 数据库带版本更新

      适用场景

  • 悲观锁适用于写多读少的情况

  • 乐观锁适用于读多写少的情况

    自旋

    了解自旋锁首先需要了解,自旋锁解决了什么问题。线程的阻塞和唤醒需要CPU的参与,然后这两动作动静都比较大,上下文切换消耗比较大,在一些锁的时间很短的情况下,阻塞和唤醒 本身的操作比业务执行的更消耗资源。

自旋锁就是在这种背景下提出的。

自旋锁主要解决锁时间很短的时候避免阻塞和唤醒,而自旋锁如果一直自旋又会带来CPU计算浪费的问题,因此不能无限制自旋。只能尝试多少次,或者是多少时间内自旋来解决问题。

自旋是利用CAS来实现的

自适应自旋则是利用JVM本身的判断,上次自旋用了多久就获得锁了,这次是否依旧自旋。如果自旋很少获得锁,那就干脆不自旋了。

公平锁和非公平锁

公平锁是指大家一起排队,先进先出,第一个到达的第一个获得锁

  • 好处: 都可以获得锁,不会出现线程饥饿的情况
  • 缺点: 粒度不够,并发较低

非公平锁是线程先去获取一次,如果获取不到进入队列(这个时候就是公平锁了)

  • 好处: 提高了并发
  • 缺点: 可能出现线程饥饿的情况

    可重入锁

    一般的锁都是可重入锁,就是当前线程是否可以多次获取锁

    共享锁和排它锁

    共享: 在有资源的情况下,线程一起分享,支持多个线程并行执行

  • 信号量

  • CountDownLatch

排他: 当前线程获取到资源后,其他线程只能等待

  • 可重入锁

    链接