不吃饭也要搞定的 —— synchronized

本文介绍了Java中synchronized锁的升级过程,从早期的重量级锁到JDK1.6后引入的偏向锁、轻量级锁和自旋锁,阐述了这些机制如何根据竞争情况自动选择,提高并发性能。同时讲解了synchronized在不同场景下的用法和锁行为.
摘要由CSDN通过智能技术生成

大家好,我是徒手敲代码。

今天来介绍一下面试中最常考的多线程知识点,synchronized。在面试当中,要求掌握 synchronized 的锁升级过程,以及常见的一些用法。看完文章之后,尽量尝试用理科思维去理解整个升级的过程,想清楚为什么要这么玩,避免死记硬背。

synchronized锁升级过程

假设在一家饭店里,客人是一个个的线程,饭店的每张桌子是同步对象,点菜这个动作是访问资源。客人如果想要点菜(访问资源),需要找店员(JVM)登记并获取桌号(锁)。

但是,早期的 synchronized 就像一个吝啬的老板,它不舍得花钱请员工来帮客人下单,必须要亲自去管理每一桌,每当有顾客想点菜的时候,都要叫老板过来,亲自下单,必须等老板处理好这一桌之后,才能轮到下一桌来点,这个过程需要消耗顾客大量的时间去等待,也就是我们所说的“重量级锁”。从 jdk1.6 开始,这个老板痛定思痛,决定来一次大刀阔斧的改革。

在 JVM 的世界里,每个对象都有一个“身份证”——MarkWord,它记录着对象的各种信息,其中就包括锁的状态,比较关键的参数是“是否偏向锁”和“锁标志位”。这就像是饭店里的每张桌子上,摆着一个标识的牌子,上面写着这张桌子目前是否有人占用,占用者是谁,以及占用的类型。

首先出来混的,是偏向锁,就像是饭店里的VIP服务。当某个顾客经常光顾同一家饭店,店员会记住这位常客,直接为他预留着常用的桌子,省去了每次询问老板的过程。在 Java 中,如果一个线程连续多次获得同一个对象的锁,那么JVM就会给该对象打上标记,形成偏向锁,后续获取锁的操作就会变得更快捷。

然而,一旦有新的顾客(线程)想要就餐,偏向锁就需要进行锁膨胀,转化为轻量级锁。轻量级锁就好像店员临时接手管理某一张桌子,快速处理多个顾客间的冲突。此时,线程会尝试通过 CAS 操作来获取锁,减少上下文切换带来的开销。

这个时候,来吃饭的客人变多了,饭店里不再只有那个熟悉的身影,就轮到了自旋锁。自旋锁就像是焦急想要吃饭的客人,在桌子旁边短暂徘徊,而不是立刻离开去排队,这样能够第一时间知道是否有空位出现。但长时间的自旋会导致CPU空转浪费资源,因此,后面又引入了自适应自旋锁这个概念,意思就是,根据历史自旋成功与否的情况,来动态调整自旋次数,实现更灵活高效的锁竞争策略。

如果自旋锁都搞不定,那就只好出最后的武器——重量级锁。它就像饭店老板亲自介入,对争执不下的桌子进行严格管理。“都别吵了,全部出去排队!”

虽然效率相对较低,但在高度竞争的情况下能够保证公平性。重量级锁会触发操作系统级别的互斥量,从而实现线程间的有效隔离,但这肯定会增加上下文切换和阻塞唤醒的开销。

总结一下,synchronized 在JDK 1.6后的设计思路,就是通过偏向锁、轻量级锁、自旋锁、重量级锁这一系列机制,根据实际情况自动选择合适的锁状态,实现了锁的精细化管理。

synchronized用法

实际编码中,synchronized可以用来修饰普通方法、静态方法、代码块

1、普通方法和代码块
public class Demo {
    public synchronized void test() {
        // 方法逻辑
    }
}
public class Demo {
    private Object tableKey = new Object();

    public void test() {
        synchronized (tableKey) {
            // 方法逻辑
        }
    }
}

这两种情况,锁的是调用 test 方法的对象。意思就是,如果有多个线程同时访问同一个对象的不同实例,它们可以并行执行同步方法;但如果多个线程试图访问同一个对象实例的同步方法,将会串行执行,也就是同一时刻,只能有一个线程进入该方法。

2、静态方法
public class Demo {
    public static synchronized void test() {
        // 方法逻辑
    }
}

这种情况,锁的是整个类。意思就是,对于这个类的所有实例,只要涉及到这个类的静态同步方法,所有线程都将共用同一把锁。所有的线程都要同呼吸,共命运。

今天的分享到这里结束了,如果你喜欢这种分享知识的方式,欢迎点赞喔

——————————————

资料获取

关注公众号”徒手敲代码“,回复“电子书”,获取腾讯大佬推荐的Java书籍💪

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值