锁的由来,及乐观锁悲观锁的应用实现优化

简介: 本篇文章我们就来聊一聊什么是锁,为什么需要锁,究竟如何加锁,当然我说的也可能有不足之处,欢迎大家积极在评论区探讨。

1 锁的由来

1.1 并发

并发其实很简单,并发就是多线程并发访问,就是有N多个线程都来获取相同的资源,

1.2 串行化

我们说的线程安全也就是多线程并发访问资源时,保证其有序性,那么如何来保证有序性呢?

1.3 锁

锁就是保证并发有序性的一种手段。及加锁可以实现线程安全。

2 那么锁该怎么加呢?

加锁时候其实就需要去考虑场景了

2.1 乐观锁 读多写少

乐观锁本质是不加锁,我们认为遇到并发写的可能性会很低,每次拿到的数据我们认为是不会被修改的,所以是不会阻塞的,但是为了保证数据的一致性,我们在并发写的时候需要再次确认一下,拿到的是不是最新的数据。如果不是,再去取一份,然后再次验证,直到验证通过后,才可以写入。

2.2 被观锁 读少写多

悲观锁就是认为写多,读少,每次读写数据时都会上锁,让其他线程想要获取资源的线程进入阻塞状态,直到当前获取到资源的线程释放资源,下一个线程才能获取到资源。

3 锁的实现

3.1 乐观锁

Java中常用的乐观锁就是CAS算法+自旋(需要考虑ABA问题,CPU性能)。

适应性自旋锁(是JVM对自旋的一种优化,会选择一个最佳时间进行自旋,而不是一直保持自旋消耗CPU资源)

实现:

// 乐观锁
public class AtomicInteger extends Number implements Serializable {  
​
    private volatile int value;  
​
    public final int get() {  
        return value;  
    }  
​
    public final int getAndIncrement() {  
        for (;;) {  
            int current = get();  
            int next = current + 1;  
            if (compareAndSet(current, next))  
                return current;  
        }  
    }  
​
    public final boolean compareAndSet(int expect, int update) {  
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  
    }  
}    

JDK1.5开始atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。

也有一些是基于版本号解决ABA问题,版本号只增不减。

3.2 悲观锁

对于Java来说,synchronized关键字和Lock的实现类都是悲观锁。

RetreenLock的原理是基于AQS,AQS是先尝试使用CAS自旋,如果获取不到就会转化为悲观锁。

悲观锁往往是需要通过阻塞线程实现的,想要更为深刻的理解悲观锁,我们就需要知道线程的各个状态。

线程的状态,如下图所示:

image.png

  • 线程A 访问资源,发现此时没有锁
  • 线程A 获取到资源,锁住资源,不允许其他线程操作
  • 线程B、C...访问资源,发现资源被锁,然后B、C...进入阻塞状态
  • 当线程A操作完成,释放资源的锁
  • 此时B、C会进入就绪状态进行竞争,能力强的得到锁(这里就引入公平锁【按先后顺序获取锁】、非公平锁的概念【强势的获取到锁】)在锁竞争时,就可能出现死锁的情况。

    锁竞争又会带出优化锁的知识点【

    • 降低锁的粒度
    • 减少持有锁的时间
    • 锁分离(读写锁分离)
    • 锁升级(对加锁的一种优化操作)】
  • 线程B 获取到锁,线程状态重新恢复到运行态,未获取到锁的继续恢复阻塞,等待时机
  • ...
目录
相关文章
|
1月前
|
算法 Java 关系型数据库
何为乐观锁和悲观锁
何为乐观锁和悲观锁
|
6月前
|
算法 Java 关系型数据库
面试必备之何谓悲观锁与乐观锁
乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。
54 1
|
XML 前端开发 Java
案例突破——悲观锁和乐观锁
案例突破——悲观锁和乐观锁
150 0
案例突破——悲观锁和乐观锁
|
算法
悲观锁和乐观锁的区别
悲观锁和乐观锁的区别
231 0
|
数据库
乐观锁和悲观锁的底层原理
乐观锁和悲观锁是并发编程中常用的两种锁机制,用于解决多线程或多进程环境下的并发访问问题。它们的底层原理和适用场景有所不同。
154 0
|
算法 Java 关系型数据库
何谓悲观锁与乐观锁
何谓悲观锁与乐观锁
|
数据采集 算法 Java
锁住它,快告诉我乐观锁与悲观锁的区别?
锁住它,快告诉我乐观锁与悲观锁的区别?
144 1
锁住它,快告诉我乐观锁与悲观锁的区别?
|
SQL 算法 安全
看完你就应该能明白的悲观锁和乐观锁
Java 按照锁的实现分为乐观锁和悲观锁,乐观锁和悲观锁并不是一种真实存在的锁,而是一种设计思想,乐观锁和悲观锁对于理解 Java 多线程和数据库来说至关重要,那么本篇文章就来详细探讨一下这两种锁的概念以及实现方式。
163 0
看完你就应该能明白的悲观锁和乐观锁
|
存储 SQL Java
面试官问你悲观锁和乐观锁的区别
面试官问你悲观锁和乐观锁的区别
163 0
|
SQL 安全 关系型数据库
悲观锁和乐观锁的区别以及实现方式
悲观锁和乐观锁的区别以及实现方式详细解答
364 0