欢迎光临
我们一直在努力

【Java 入门 Day27】 多线程万字拆解(中篇):同步锁 + 线程通信,解决并发数据翻车惨案

家人们!上篇学会怎么开多线程,但是多个人(线程)抢同一个共享数据的时候,经常出现数据错乱、重复计算,今天专门讲锁机制和线程通信,根治并发脏数据!

一、核心前置概念

  • 临界资源:多个线程同时操作的同一个共享对象,比如售票系统的总票数;
  • 原子操作:不可拆分完整操作,要么全部执行成功,要么完全不执行,不能中途被 CPU 切换打断;
  • 线程同步目的:保护原子操作不被线程插队打断,保证临界资源数据不出错。
  • 二、synchronized 同步锁两种写法(唯一内置锁)

    1. 同步代码块(精准加锁,推荐)

    语法:

    java运行

    synchronized(临界资源对象){
    // 原子操作,多线程排队执行
    }

    执行原理: 线程进入代码块前,先抢对象锁标记;抢到才能执行内部代码,执行完自动释放锁;没抢到锁直接进入 Blocked 阻塞蹲坑,等别人释放再抢。

    2. 同步方法(等价锁 this)

    用 synchronized 修饰普通方法,等价于整个方法套synchronized(this)代码块,锁当前实例对象。

    java运行

    public synchronized void sellTicket(){
    // 售票原子逻辑
    }

    短板:锁粒度太大,整个方法全部上锁,并发效率低,只适合短逻辑。

    三、线程之间通信:Object 三巨头 wait/notify/notifyAll

    所有对象自带这三个方法,必须写在对应对象的同步锁代码块里才能调用。

  • wait():当前线程释放锁,进入无限等待池,原地躺平等别人喊醒;
  • notify():随机叫醒等待池里一条等待线程;
  • notifyAll():一次性叫醒等待池里全部等待线程;
  • 经典面试题 sleep () vs wait () 完整对比

    四、拓展显式锁 Lock & 读写锁 ReadWriteLock

    synchronized 是隐式锁,自动上锁释放;Lock 手动控制,灵活性拉满。

  • ReentrantLock 可重入锁
  • java运行

    Lock lock = new ReentrantLock();
    try{
    lock.lock(); // 手动上锁
    // 业务代码
    }finally{
    lock.unlock(); // 必须放finally,防止异常死锁
    }

  • 读写锁 ReentrantReadWriteLock 分读锁、写锁,规则:
    • 读读:不互斥,多线程同时读,效率高;
    • 读写 / 写读 / 写写:全部互斥,排队执行; 适用场景:项目查询多、修改极少的业务,大幅提升并发读取速度。

    五、线程不安全集合避坑(面试高频对比)

    1. 老古董同步集合(效率拉胯)

    Vector、Hashtable:方法全加 synchronized,单锁全集合,并发性能极低,新项目基本弃用;

    2. 工具类包装同步集合

    Collections.synchronizedList/Set/Map():给普通集合套一层同步锁,全局单锁,并发效率一般;

    3. JUC 高性能线程安全集合(生产首选)

  • CopyOnWriteArrayList 读不加锁,写的时候复制一份新数组修改,写完覆盖旧数组;读多写少场景天花板,大量写入性能暴跌;
  • ConcurrentHashMap 分段锁(JDK7)/CAS+synchronized(JDK8),锁粒度细分,并发远超 Hashtable,不允许 key/value 为 null;
  • ConcurrentLinkedQueue:无锁 CAS 队列,高性能并发排队容器。
  • 两道必背面试对比题

  • ArrayList vs CopyOnWriteArrayList ArrayList 线程不安全、读写都快;CopyOnWriteArrayList 线程安全,读极快、写很慢,适合查询多场景;
  • HashMap vs ConcurrentHashMap HashMap 线程不安全,允许 null 键值;ConcurrentHashMap 线程安全,分段锁提升并发,禁止 null 键值。

  • 中篇小结 现在我们掌握了锁机制、线程通信、线程安全集合,解决多线程并发数据错乱问题。下一篇讲开发生产必用线程池、Callable 带返回值线程、阻塞队列,企业项目 90% 多线程场景全靠线程池!

     

    赞(0)
    未经允许不得转载:171主机测评 » 【Java 入门 Day27】 多线程万字拆解(中篇):同步锁 + 线程通信,解决并发数据翻车惨案
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址