常见的锁策略

简介: 常见的锁策略

乐观锁和悲观锁

乐观锁:在获取锁时预期锁的竞争不太激烈,在执行任务时先不进行加锁,或者是少加锁(或者是等到需要加锁的时候再加锁)

悲观锁:在获取锁时预期锁的竞争非常激烈,在执行任务前必须进行加锁操作,加锁之后才能去执行任务。

我们用现实的一个例子来对此进行说明:

ad0c0f02008769168459bdf3060ae6c8.png

对乐观锁的和悲观锁的总计而言就是根据对锁的态度执行加锁的操作。

轻量级锁和重量级锁

轻量级锁:加锁的过程比较简单,需要消耗的资源相对较少,典型的就是在用户态完成加锁操作(在JAVA层面就能完成的加锁操作)

重量级锁:加锁的过程比较复杂,需要消耗的资源相对较多,典型的是在内核态完成的加锁操作

而乐观锁的锁策略是能不加锁就加锁,相对而言消耗的资源比较少,所以乐观锁是一种轻量级锁

悲观锁的策略是在执行任务前必须加锁,这样消耗的资源就比较多,所以悲观锁是一种重量级锁

自旋锁和挂起等待锁

自旋锁:不断去询问锁资源是否被释放,一旦锁资源被释放,就直接获取锁资源

挂起等待锁:不主动询问锁资源,而是通过系统的调度去竞争锁资源

我们用现实的一个例子来对概念进行解释:

我跟朋友越好了吃饭,当我到他家楼下的时候他还没有下楼,这时候我给他打电话催促他抓紧下来,他说马上就下来了,过了一小会儿他还没有下来,我继续打电话催促,(不断询问)直到他说他下来了,我告诉他我的具体位置(获取锁资源)

而挂起等待锁的实际场景是,我到他楼下之后不催他下来,而是在那玩手机,等他下来之后等他告诉我,(系统调度通知)然后我告诉他我的具体位置

自旋锁的优缺点:

①在获取锁资源之前的不断询问锁资源是否被释放是纯用户态的操作,是一种轻量级锁

②由于不断询问锁资源是否被释放,当锁资源被释放后能第一时间获取到获取到锁

③不断的循环相对而言消耗资源比较多(缺)。

在实际的业务场景中,我们可以通过控制自旋的次数来降低资源的消耗

挂起等待锁的优缺点:

①通过线程阻塞和就绪状态的切换来获取锁资源

②锁资源一旦释放无法第一时间获取锁

③是通过系统内核来进行处理的

自旋锁是一种轻量级锁的具体体现,挂起等待锁是一种重量级锁的具体体现

读写锁和普通互斥锁

读写锁:

读锁:在进行读操作时加锁(共享锁),多个锁可以共存,同时加多个读锁并不相互影响。

写锁:在进行写操作时加锁(排它锁),只能有一个写锁在执行任务,和其他锁是互斥的

写锁和写锁不能共存

写锁和读锁不能共存

读锁和读锁可以共存

为什么要有读写锁?

我们在进行读操作时会有激烈的锁竞争,但是读操作按照真实的业务场景彼此之间是不相互影响的,所以所有的读都可以并发执行(高效率),当一个操作是读操作,携带的锁是读锁,这时候可以直接进行读取,不产生锁竞争,进而降低了资源的消耗,同时提高了程序运行的效率。如果这时候的操作是写操作时,让它等待。

读写锁相当于在给锁打上了'读'和'写'的标签,在高并发读的应用场景中,锁竞争会大大降低,进而提高程序的运行效率

互斥锁:多个锁之间存在锁竞争,只有当一个线程释放锁之后,别的线程才能来竞争锁资源,我们之前几乎所有的锁都是互斥锁

公平锁和非公平锁

公平锁:讲究先来后到,先排队的先获取锁,后排队的后获取锁

非公平锁:多个线程一起竞争锁资源,谁抢到就是谁的

如果想要创建公平锁,需要额外消耗一些资源,比如锁的实现过程要记录哪个线程先来后到,需要一种数据结构把线程组织起来,这也是一种资源的消耗,这就意味着公平锁的效率必然会受到影响。

而非公平锁就没有这种资源的消耗,所以在java和其他用锁的环境中,默认的锁资源都是非公平锁,而java中的juc中有一个类专门实现了公平锁

synchronized是一把非公平锁

可重入锁和不可重入锁

可重入锁:对于同一个线程的同一把锁,允许上锁多次而不造成死锁。

不可重入锁:对于同一把锁多次不允许多次上锁

我们需要注意的是:对于同一把锁多次上锁同时必须进行多次解锁,否则其他线程无法获取该锁

我们从这六个概念的角度来分析synchronized是一把怎样的锁?

c533913232be77a69177a5f14f4cd14e.png

  1. 既是乐观锁,又是悲观锁
  2. 既是轻量级锁,又是重量级锁
  3. 既是自旋锁,又是挂起等待锁
  4. 是普通互斥锁
  5. 是非公平锁
  6. 是可重入锁
相关文章
|
6月前
|
安全 开发工具
防止死锁的关键策略
防止死锁的关键策略包括:避免持有多个锁,按相同顺序获取,设置锁获取超时,减小锁粒度,以及利用死锁检测工具。确保线程安全,减少锁竞争,可提高系统并发性能。
65 1
|
6月前
|
C++
多线程(锁策略, synchronized 对应的锁策略)
多线程(锁策略, synchronized 对应的锁策略)
52 2
|
6月前
|
安全 Java 编译器
Java并发编程中的锁优化策略
【5月更文挑战第30天】 在多线程环境下,确保数据的一致性和程序的正确性是至关重要的。Java提供了多种锁机制来管理并发,但不当使用可能导致性能瓶颈或死锁。本文将深入探讨Java中锁的优化策略,包括锁粗化、锁消除、锁降级以及读写锁的使用,以提升并发程序的性能和响应能力。通过实例分析,我们将了解如何在不同场景下选择和应用这些策略,从而在保证线程安全的同时,最小化锁带来的开销。
|
Java 程序员 调度
介绍几个常见的锁策略!
介绍几个常见的锁策略!
56 0
|
Java 调度
关于常见的锁策略
关于常见的锁策略
63 0
|
6月前
|
安全 Java 调度
常见的锁策略
常见的锁策略
|
6月前
|
安全 Java 编译器
常见锁策略
常见锁策略
44 0
|
6月前
|
Java 调度 数据库
锁策略之干货分享,确定不进来看看吗?️️️
锁策略之干货分享,确定不进来看看吗?️️️
92 0
|
6月前
|
Java 调度 C++
多线程之常见的锁策略
多线程之常见的锁策略
|
安全 Java 程序员
多线程(八):常见锁策略
多线程(八):常见锁策略
192 0
多线程(八):常见锁策略