news 2026/5/1 11:12:14

Java多线程同步与互斥实现方法大揭秘!(面试必看)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java多线程同步与互斥实现方法大揭秘!(面试必看)

文章目录

  • Java多线程同步与互斥实现方法大揭秘!(面试必看)
    • 一、前言:多线程的那些事儿
    • 二、Java多线程同步与互斥的核心概念
    • 三、Java多线程同步与互斥的实现方法
      • 1. `synchronized`关键字:最简单的同步方式
        • 示例:用`synchronized`修饰方法
        • 示例:用`synchronized`修饰代码块
        • 优缺点分析:
      • 2. `ReentrantLock`:更灵活的同步工具
        • 示例:基本用法
        • 示例:可中断的锁
        • 优缺点分析:
      • 3. `Semaphore`:控制并发访问的数量
        • 示例:限制数据库连接数
        • 优缺点分析:
      • 4. `CountDownLatch`和`CyclicBarrier`:协调多线程执行
        • 示例:用`CountDownLatch`等待所有线程完成
        • 示例:用`CyclicBarrier`实现循环栅栏
        • 优缺点分析:
      • 5. `ReadWriteLock`:实现读写分离
        • 示例:用`ReentrantReadWriteLock`
        • 优缺点分析:
      • 6. `Atomic`类:无锁同步
        • 示例:用`AtomicInteger`
        • 优缺点分析:
      • 总结
    • 此外,合理的设计和清晰的代码结构也能帮助减少并发问题的发生。
      • 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

Java多线程同步与互斥实现方法大揭秘!(面试必看)

大家好,欢迎来到闫工的技术博客!今天我们要聊一个在Java开发中非常重要的话题——多线程同步与互斥的实现方法。作为一个Java工程师,掌握这部分知识是必不可少的,尤其是当你准备面试的时候,这个知识点几乎是必考的!所以,赶紧坐稳了,跟着闫工一起深入探讨一下。


一、前言:多线程的那些事儿

在聊同步与互斥之前,我们先来简单回顾一下Java中的多线程是什么。多线程是指在一个程序中同时运行多个执行路径的能力,这样可以提高程序的效率和响应速度。比如说,在一个网页应用中,主线程负责处理用户请求,而其他线程负责处理数据库查询、文件上传等任务,这样整个系统的性能就会更好。

但是,多线程编程有一个大坑——竞态条件(Race Condition)。当多个线程同时访问和修改共享资源时,就可能出现数据不一致或者程序崩溃的情况。举个例子,假设两个线程同时操作一个变量count,它们都试图将count加1,但结果可能因为执行顺序的问题导致count只增加了一次而不是两次。

所以,为了防止这种情况发生,我们需要使用同步和互斥机制来控制线程的执行顺序。接下来,我们就来看看Java中有哪些实现方法。


二、Java多线程同步与互斥的核心概念

在深入具体实现之前,我们先明确几个核心概念:

  1. 同步(Synchronization)
    同步是指在同一时间点上只能有一个线程执行某个代码块或方法。它的目的是为了防止多个线程同时操作共享资源,从而避免竞态条件的发生。

  2. 互斥(Mutex/Exclusive Access)
    互斥是一种更严格的同步机制,它确保在任何时刻只有一个线程可以访问某个资源或代码块。

  3. 临界区(Critical Section)
    临界区指的是那些需要被严格控制的共享资源访问区域。在这个区域内,必须实施同步和互斥机制。

了解了这些概念后,我们就可以开始探索具体的实现方法了。


三、Java多线程同步与互斥的实现方法

1.synchronized关键字:最简单的同步方式

synchronized是Java中最基础也是最常见的同步工具。它可以修饰方法或者代码块,确保在同一个时间点上只有一个线程可以执行被锁定的代码。

示例:用synchronized修饰方法
publicclassCounter{privateintcount=0;publicsynchronizedvoidincrement(){// 使用synchronized关键字修饰方法count++;}publicsynchronizedintgetCount(){returncount;}}
示例:用synchronized修饰代码块
publicclassAccount{privatedoublebalance;publicvoidwithdraw(doubleamount){synchronized(this){// 使用synchronized代码块if(balance>=amount){balance-=amount;}else{System.out.println("余额不足!");}}}publicvoiddeposit(doubleamount){synchronized(this){// 同一个锁对象,确保互斥balance+=amount;}}}
优缺点分析:
  • 优点:简单易用,语法清晰。
  • 缺点:只能实现简单的同步,无法支持复杂的同步需求(比如读写锁、超时等待等)。

2.ReentrantLock:更灵活的同步工具

如果synchronized关键字不能满足你的需求,那么Java并发包中的ReentrantLock就是更好的选择。它提供了更多的控制选项,比如公平锁、可中断锁等。

示例:基本用法
importjava.util.concurrent.locks.ReentrantLock;publicclassCounter{privateintcount=0;privateReentrantLocklock=newReentrantLock();publicvoidincrement()throwsInterruptedException{lock.lock();// 尝试获取锁,如果被占用则阻塞等待try{count++;}finally{lock.unlock();// 释放锁}}publicintgetCount()throwsInterruptedException{lock.lock();try{returncount;}finally{lock.unlock();}}}
示例:可中断的锁
publicclassInterruptibleLockExample{privateReentrantLocklock=newReentrantLock();publicvoiddoSomething()throwsInterruptedException{booleaninterrupted=false;while(!interrupted){try{lock.lockInterruptibly();// 可以响应中断的lock方法System.out.println("执行任务...");interrupted=true;}catch(InterruptedExceptione){System.out.println("被中断了,继续等待锁...");interrupted=false;}}}}
优缺点分析:
  • 优点:灵活性高,支持公平锁、可中断锁等高级特性。
  • 缺点:需要手动管理锁的获取和释放,增加了代码复杂度。

3.Semaphore:控制并发访问的数量

如果你的需求不是严格的互斥,而是希望同时允许一定数量的线程访问某个资源,那么Semaphore就是你的不二选择。它可以看作是一种“信号量”,用来控制同时可以执行某项操作的线程数量。

示例:限制数据库连接数
importjava.util.concurrent.Semaphore;publicclassDatabaseConnectionPool{privatestaticfinalintMAX_CONNECTIONS=5;privateSemaphoresemaphore=newSemaphore(MAX_CONNECTIONS);publicvoidgetConnection()throwsInterruptedException{semaphore.acquire();// 尝试获取信号量,如果不可用则阻塞等待try{System.out.println("成功获取数据库连接!");// 模拟使用连接的时间Thread.sleep(1000);}finally{semaphore.release();// 释放信号量System.out.println("已释放数据库连接!");}}publicstaticvoidmain(String[]args)throwsInterruptedException{DatabaseConnectionPoolpool=newDatabaseConnectionPool();for(inti=0;i<10;i++){Threadthread=newThread(()->{try{pool.getConnection();}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});thread.start();// 适当延迟,让线程有机会交替执行Thread.sleep(50);}}}
优缺点分析:
  • 优点:能够灵活控制并发访问数量。
  • 缺点:实现相对复杂,需要理解信号量的工作原理。

4.CountDownLatchCyclicBarrier:协调多线程执行

有时候,我们需要在多个线程完成各自的任务后,再统一进行后续操作。这时候可以使用CountDownLatchCyclicBarrier来实现线程间的同步。

示例:用CountDownLatch等待所有线程完成
importjava.util.concurrent.CountDownLatch;publicclassCountDownLatchExample{publicstaticvoidmain(String[]args)throwsInterruptedException{intnumberOfThreads=5;CountDownLatchlatch=newCountDownLatch(numberOfThreads);for(inti=0;i<numberOfThreads;i++){Threadthread=newThread(()->{System.out.println("线程"+Thread.currentThread().getId()+"正在执行任务...");try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}latch.countDown();// 通知计数器减一});thread.start();}// 等待所有线程完成latch.await();System.out.println("所有线程已完成任务!");}}
示例:用CyclicBarrier实现循环栅栏
importjava.util.concurrent.CyclicBarrier;publicclassCyclicBarrierExample{publicstaticvoidmain(String[]args)throwsInterruptedException{intnumberOfThreads=3;CyclicBarrierbarrier=newCyclicBarrier(numberOfThreads);for(inti=0;i<numberOfThreads;i++){Threadthread=newThread(()->{System.out.println("线程"+Thread.currentThread().getId()+"到达栅栏,等待其他线程...");try{barrier.await();}catch(InterruptedException|BrokenBarrierExceptione){// 处理异常}System.out.println("线程"+Thread.currentThread().getId()+"继续执行任务...");});thread.start();}}}
优缺点分析:
  • 优点:能够灵活地协调多个线程的执行顺序。
  • 缺点:需要正确配置和使用,否则可能导致死锁或其他问题。

5.ReadWriteLock:实现读写分离

在某些场景下,我们希望允许多个线程同时读取资源,但只允许一个线程写入资源。这时可以使用ReadWriteLock来实现读写分离的同步策略。

示例:用ReentrantReadWriteLock
importjava.util.concurrent.locks.ReentrantReadWriteLock;publicclassReadWriteLockExample{privateReentrantReadWriteLocklock=newReentrantReadWriteLock();privateintcount=0;publicvoidread()throwsInterruptedException{lock.readLock().lock();// 获取读锁try{System.out.println("线程"+Thread.currentThread().getId()+"正在读取数据,count="+count);}finally{lock.readLock().unlock();}}publicvoidwrite()throwsInterruptedException{lock.writeLock().lock();// 获取写锁try{System.out.println("线程"+Thread.currentThread().getId()+"正在写入数据...");count++;}finally{lock.writeLock().unlock();}}}
优缺点分析:
  • 优点:提高了读操作的吞吐量,适用于读多写少的场景。
  • 缺点:需要正确管理锁的获取和释放,否则可能导致性能问题。

6.Atomic类:无锁同步

如果你的场景只需要原子地修改某个变量,那么可以考虑使用Java内存模型中的Atomic类。它们通过CAS(Compare-and-Swap)操作实现无锁同步,性能非常高。

示例:用AtomicInteger
importjava.util.concurrent.atomic.AtomicInteger;publicclassAtomicIntegerExample{privateAtomicIntegercount=newAtomicInteger(0);publicvoidincrement(){// 原子地增加1,并返回新的值System.out.println("线程"+Thread.currentThread().getId()+"将count从"+(count.get())+"改为"+count.incrementAndGet());}publicstaticvoidmain(String[]args){AtomicIntegerExampleexample=newAtomicIntegerExample();for(inti=0;i<5;i++){Threadthread=newThread(example::increment);thread.start();}}}
优缺点分析:
  • 优点:性能极高,适用于简单的原子操作。
  • 缺点:只能处理单个变量的原子操作,无法处理复杂的同步逻辑。

总结

在Java中,线程间通信和共享数据需要谨慎处理以避免竞态条件、死锁和其他并发问题。选择合适的同步工具取决于具体的应用场景:

  • 简单的读写操作:考虑使用Atomic类。
  • 多线程协作:可以使用CountDownLatchCyclicBarrier
  • 读多写少的场景:适合使用ReadWriteLock
  • 需要协调多个任务完成顺序:可以考虑CompletableFuture
  • 复杂的同步需求:可能需要结合多种工具,或者自定义锁策略。

此外,合理的设计和清晰的代码结构也能帮助减少并发问题的发生。

📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?

闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!

✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!

📥免费领取👉 点击这里获取资料

已帮助数千位开发者成功上岸,下一个就是你!✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 4:52:09

水印叠加功能建议:LobeChat输出内容可追溯

水印叠加功能建议&#xff1a;LobeChat输出内容可追溯 在AI生成内容&#xff08;AIGC&#xff09;日益泛滥的今天&#xff0c;一条看似合理的建议、一份结构清晰的报告&#xff0c;可能并非出自人类之手。当企业员工使用同一个LobeChat实例协作办公时&#xff0c;谁该为一段错误…

作者头像 李华
网站建设 2026/5/1 6:46:24

ARM架构服务器部署LobeChat性能基准测试

ARM架构服务器部署LobeChat性能基准测试 在AI应用快速落地的今天&#xff0c;越来越多企业与开发者开始关注一个问题&#xff1a;如何在保障响应能力的同时&#xff0c;降低大模型服务的能耗与成本&#xff1f;尤其是在边缘节点、内网环境或长期运行的私有化场景中&#xff0c;…

作者头像 李华
网站建设 2026/5/1 9:33:20

还在为论文AIGC率高发愁?8个写论文AI工具,真实参考文献,低至9%!

你的“高效捷径”&#xff0c;可能正将你引向学术深渊 你是否还在为DDL临近而抓狂&#xff0c;打开空白文档大脑一片空白&#xff1f;你是否曾将论文段落丢给通用AI&#xff0c;指望它帮你“妙笔生花”&#xff1f;你是否在收到查重报告&#xff0c;看到刺眼的“高AIGC风险”时…

作者头像 李华
网站建设 2026/5/1 7:45:06

知网AIGC痕迹太重了怎么办?7个降AI率工具,快速降论文AI率

市场上的降AI率工具良莠不齐&#xff0c;如何科学判断降AI率效果是很多学生、老师最关心的问题&#xff0c;担心降不来AI率&#xff0c;耽误时间还花不少钱。 本文将从以下五个维度系统&#xff0c;分析2025年主流的8个降AI工具&#xff0c;教大家如何选择适合自己的降AIGC工具…

作者头像 李华
网站建设 2026/5/1 5:49:55

LobeChat语音交互体验实测:真正实现自然人机沟通

LobeChat语音交互体验实测&#xff1a;真正实现自然人机沟通 在智能助手越来越频繁地出现在我们生活中的今天&#xff0c;一个现实问题逐渐浮现&#xff1a;为什么用了这么多年AI聊天工具&#xff0c;我们还是觉得“它不像人”&#xff1f;打字输入、等待回复、再逐行阅读——这…

作者头像 李华
网站建设 2026/5/1 8:57:25

Git第一次提交代码到远程仓库

一、Git第一次提交代码到远程仓库 第一步&#xff1a;git init 初始化项目文件夹第二步&#xff1a;git add . 键所有文件添加到暂存区第三步&#xff1a;git commit -m “first commit” 提交到本地仓库第四步&#xff1a;git remote add origin 远程地址&#xff08;git bran…

作者头像 李华