Java的synchronized:从入门到“秃头”的终极指南

Java的synchronized:从入门到"秃头"的终极指南


一、介绍:synchronized是什么?

synchronized是Java中的"保安大哥",专门负责在多线程环境下维持秩序,确保共享资源不被"哄抢"。它的核心使命是解决线程安全问题,保证原子性(操作不可分割)、可见性(修改立即可见)和有序性(代码顺序执行)。

为什么需要它?

想象两个线程同时修改银行账户余额,如果没有同步机制,结果可能像两个人在同一张纸上乱涂乱画,最终余额变成谜团。而synchronized会大喊:"排好队,一个一个来!"。


二、用法:三种姿势,总有一款适合你

  1. 修饰实例方法

    锁住当前对象实例,适用于保护对象级别的共享资源。

    java 复制代码
    public synchronized void transferMoney() { /* 转账逻辑 */ }
  2. 修饰静态方法

    锁住整个类,适用于保护类级别的静态资源。

    java 复制代码
    public static synchronized void updateConfig() { /* 更新全局配置 */ }
  3. 修饰代码块

    灵活指定锁对象,适合只保护部分代码的场景。

    java 复制代码
    public void addToCart() {
        synchronized (cartLock) { /* 加购逻辑 */ }
    }

    注意 :别用String或基本类型包装类当锁,容易踩坑(比如字符串常量池的缓存问题)。


三、案例:代码中的"锁"事剧场

场景1 :普通方法同步

两个线程调用同一个对象的同步方法,结果像排队上厕所------必须等前一个人出来。

场景2 :静态方法同步

即使创建了多个对象实例,静态方法同步也会锁住整个类,相当于"全店打烊,只服务一个人"。

场景3 :代码块同步

只锁住关键代码,其他代码自由飞翔,性能和安全性兼得。


四、原理:锁的"变形记"

从Java 6开始,synchronized开启了"智能模式",根据竞争激烈程度自动升级锁状态:

  1. 无锁:对象刚出生,人畜无害。
  2. 偏向锁:假设只有一个线程访问,直接在对象头贴个"VIP标签"(线程ID),省去加锁步骤。
  3. 轻量级锁:多个线程交替访问,通过CAS自旋(像在锁门口徘徊)尝试获取锁,避免阻塞。
  4. 重量级锁:竞争激烈时,召唤操作系统级互斥量,线程排队等叫号,性能开销大但公平。

锁升级的目的:像饭店老板根据客流量调整服务员数量,既省成本又保效率。


五、对比:synchronized vs 其他同步工具

  1. synchronized vs volatile

    • volatile只管可见性,不保原子性(比如i++仍需同步)。
    • synchronized是"全能选手",但可能引发线程阻塞。
  2. synchronized vs ReentrantLock

    • synchronized自动释放锁,ReentrantLock需手动unlock()(忘写就死锁警告!)。
    • ReentrantLock支持可中断、公平锁、多条件变量,适合复杂场景。

六、避坑指南:别让锁"锁"住你的智商

  1. 不完全同步

    java 复制代码
    // set方法同步,get方法不同步 → 可能读到旧值!
    public synchronized void setX(int x) { this.x = x; }
    public int getX() { return x; } // 应加synchronized或用volatile
  2. 锁对象中途变心

    java 复制代码
    synchronized (array[0]) { 
        array[0] = new Object(); // 锁对象被替换,同步失效!
    }
  3. 在循环中滥用锁

    频繁加锁会导致性能"雪崩",改用原子类(如AtomicInteger)或并发集合更香。


七、最佳实践:做个锁的"时间管理大师"

  1. 锁粒度要细:只锁必要代码,像只保护保险箱而不是整个房间。
  2. 用final对象当锁:防止锁对象被意外替换。
  3. 避免嵌套锁:小心死锁,像两个人互相等对方先放手。
  4. 优先选代码块:比锁方法更灵活,减少阻塞范围。

八、面试考点:高频灵魂拷问

  1. 锁升级过程(偏向锁→轻量级锁→重量级锁)。
  2. synchronized和ReentrantLock的区别(自动vs手动、功能扩展性)。
  3. 为什么synchronized是非公平锁
    (答:唤醒线程随机,插队更高效,但可能"饿死"老实线程)。

九、总结:synchronized的"人生哲学"

  • 优点:简单易用、自动释放、可重入。
  • 缺点:无法中断、不支持超时、非公平。
  • 适用场景 :低竞争或简单同步需求;高竞争时考虑ReentrantLockStampedLock

最后提醒:锁虽好,但别滥用!多线程编程就像开车,安全第一,性能第二。


参考资料

(想要更深入细节?点击链接直达原文,开启"秃头"之旅吧!)

相关推荐
王翼鹏1 分钟前
Spring boot 策略模式
java·spring boot·策略模式
lagrahhn7 分钟前
记一次idea中lombok无法使用的解决方案
java·ide·intellij-idea
爷一隐居青楼7 分钟前
PGSQL结合linux cron定期执行vacuum_full_analyze命令
java·linux·服务器
啾啾Fun18 分钟前
【Java实战】低侵入的线程池值传递
java·线程池·ttl
哈哈哈哈哈哈哈哈哈...........35 分钟前
【Java】ForkJoin 框架
java·开发语言
何中应1 小时前
【设计模式-4.6】行为型——状态模式
java·设计模式·状态模式
白日依山尽yy1 小时前
spring事务的面试题 —— 事务的特性、传播机制、隔离机制、注解
java·数据库·spring
欧阳有财1 小时前
[java八股文][JavaSpring面试篇]SpringBoot
java·spring boot·面试
杨DaB1 小时前
【JavaWeb】基本概念、web服务器、Tomcat、HTTP协议
java·笔记·学习·java-ee
BTU_YC1 小时前
tomcat yum安装
java·linux·tomcat