Java多线程八股(一), 锁策略,synchronized锁策略详解

目录:

一.常见的锁策略:

二.synchronized锁策略详情:



一.常见的锁策略:
注意: 接下来讲解的锁策略不仅仅是局限于 Java . 任何和 "锁" 相关的话题, 都可能会涉及到以下内容. 这些特性主要是给锁的实现者来参考的.

1.乐观锁 vs 悲观锁:

不是某一种特殊的锁,而是某个锁具有悲观或者乐观特性

乐观 :加锁的时候预测接下来的锁竞争不激烈,就不需要做额外的工作

悲观:加锁的时候预测接下来的锁竞争激烈,就需要针对这样的激烈情况做额外的工作


2.重量级锁 vs 轻量级锁:

遇到悲观或者乐观的解决方案

轻量级锁:应对乐观场景,此时付出的代价小,比较高效。

重量级锁:应对悲观场景,此时付出的代价大,比较低效。

注意: synchronized 开始是⼀个轻量级锁. 如果锁冲突比较严重, 就会变成重量级锁


3.自旋锁 vs 挂起等待锁:

**自旋锁:**轻量级锁的经典案例,应用程序级别的量级,加锁的时候发现竞争一般不会加入阻塞等待的状态,而是采用忙等形式进行等待。

忙等:锁竞争不激烈,在某时刻解锁会再很短时间内又拿到锁,多次这样处理,不会进行阻塞等待

挂起等待锁:重量级锁的经典案例,操作系统内核级别的量级,加锁的时候竞争激烈会使线程进入阻塞等待,后续需要内核唤醒


4.普通互斥锁 vs 读写锁:

一个线程对于数据的访问, 主要存在两种操作: 读数据 和 写数据.
两个线程都只是读⼀个数据, 此时并没有线程安全问题. 直接并发的读取即可.
两个线程都要写⼀个数据, 有线程安全问题.
一个线程读另外一个线程写, 也有线程安全问题.

读写锁就是把读操作和写操作区分对待分别进行加锁.

Java 标准库提供了 ReentrantReadWriteLock 类, 实现了读写锁.

ReentrantReadWriteLock.ReadLock 类表⽰⼀个读锁. 这个对象提供了 lock / unlock ⽅法
进行加锁解锁.
ReentrantReadWriteLock.WriteLock 类表⽰⼀个写锁. 这个对象也提供了 lock / unlock
⽅法进⾏加锁解锁.

注意:保证读锁与读锁之间不互斥,读锁与写锁之间互斥,写锁与写锁之间互斥。


5.可重入锁 vs 不可重入锁:

一个线程一把锁**,重复加锁多次,阻塞等待就是不可重入锁,没有阻塞等待就是可重入锁**

我们Java中的synchronized锁是可重入锁


**6.**公平锁 vs 非公平锁:

公平锁: 遵守 "先来后到"
非公平锁: 不遵守 "先来后到"
这就好比一群男生追同一个女神. 当女神和前任分手之后, 先来追女神的男生上位, 这就是公平锁; 如果是女神不按先后顺序挑一个自己看的顺眼的, 就是非公平锁.



二.synchronized锁策略详情:

1.锁升级:

我们的场景不同,锁的处理会又差异:

无锁--->偏向锁--->自旋等待锁(轻量级)--->挂起等待锁(重量级)


解释 偏向锁:在锁竞争很少下synchronized,可能不会真的加锁,而是做一些简单的标记比如布尔类型标记一下,这个量级相比于加锁解锁效率高很多,如果没有其他线程来竞争这个锁,当前线程执行到要解锁的时候,就只是去除一下这个标记。以上解释就是偏向锁的处理。

如果有其他线程来竞争这把锁了,这个偏向锁就会真的加锁,会变成自旋锁,如果线程竞争激烈会进一步变成挂起等待锁这样的重量级锁

注意:jvm中只提供锁升级,不提供锁降级


2.锁消除:

锁消除也是编译器优化的一种体现,编译器会并判断你的当前代码,是否需要加锁,如果不需要加锁,而你加了synchronized编译器会自动把synchronized去掉。


3.锁粗化:

锁的粒度:加锁和解锁中间,包含的代码越多就认为锁粒度越粗;包含的代码越少i就认为锁粒度越细。 (代码不能只看数量多,逻辑和被执行的多少也要关注)

粗化就是如果,反复针对细粒度的代码加锁就会被优化为粗粒度


这种情况就建议锁粗化:

java 复制代码
 public static int count = 0;
    public static void main(String[] args) {
        Object locker = new Object();

        Thread t1 = new Thread(()->{
            synchronized (locker) {
                count++;
            }

            synchronized (locker) {
                count++;
            }

            synchronized (locker) {
                count++;
            }
        });

        t1.start();
    }
相关推荐
Dovis(誓平步青云)3 分钟前
总用电下降了,为什么家庭能源看板仍然提示异常
java·开发语言·数据库·人工智能·算法·电脑·能源
程序猿乐锅3 分钟前
【从0-1学习Python | 第四篇】Python 字符串和元组
java·开发语言·笔记·后端·python·学习
开开心心就好6 分钟前
Windows视频播放器推荐,精简版体积更小
java·服务器·开发语言·eclipse·pdf·ocr·音视频
开开心心就好6 分钟前
A3的PDF怎么切成A4?拖一下分割线就行
服务器·开发语言·python·算法·pdf·ocr·tornado
小黄人软件8 分钟前
python 模块(Module)与包(Package)的区别,python xxx.py、python -m xxx 和 import xxx 三者的区别
开发语言·python
PHP实战开发录8 分钟前
PHP中文文件名为什么乱码
开发语言·php
Rain的Java大神之路29 分钟前
10 万人抢 2000 个座位,电影票选座系统怎么防超卖?一文讲透大厂高频场景题
java·后端·面试
阿里嘎多学长32 分钟前
2026-10-13 GitHub 热点项目精选
开发语言·程序员·github·代码托管
砚底藏山河35 分钟前
量化新手误区:因子计算与行情数据的工程化解耦
java·数据库·python·金融
威哥爱编程37 分钟前
【AI全栈12-07】Spring Boot 用 Agent 自动完成多步运营任务
java·spring boot·后端