Java 并发 Bug 深度分析与实战

Java 并发 Bug 深度分析与实战

并发编程中隐藏着各种难以发现的 Bug,本文深入分析 Java 并发编程中常见的问题,包括死锁、竞态条件、内存可见性问题等,并提供实用的排查和解决方案。

Java 并发 Bug 总览

#mermaid-svg-8T5XaxzkprBt4u25{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8T5XaxzkprBt4u25 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8T5XaxzkprBt4u25 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8T5XaxzkprBt4u25 .error-icon{fill:#552222;}#mermaid-svg-8T5XaxzkprBt4u25 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8T5XaxzkprBt4u25 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8T5XaxzkprBt4u25 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8T5XaxzkprBt4u25 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8T5XaxzkprBt4u25 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8T5XaxzkprBt4u25 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8T5XaxzkprBt4u25 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8T5XaxzkprBt4u25 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8T5XaxzkprBt4u25 .marker.cross{stroke:#333333;}#mermaid-svg-8T5XaxzkprBt4u25 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8T5XaxzkprBt4u25 p{margin:0;}#mermaid-svg-8T5XaxzkprBt4u25 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8T5XaxzkprBt4u25 .cluster-label text{fill:#333;}#mermaid-svg-8T5XaxzkprBt4u25 .cluster-label span{color:#333;}#mermaid-svg-8T5XaxzkprBt4u25 .cluster-label span p{background-color:transparent;}#mermaid-svg-8T5XaxzkprBt4u25 .label text,#mermaid-svg-8T5XaxzkprBt4u25 span{fill:#333;color:#333;}#mermaid-svg-8T5XaxzkprBt4u25 .node rect,#mermaid-svg-8T5XaxzkprBt4u25 .node circle,#mermaid-svg-8T5XaxzkprBt4u25 .node ellipse,#mermaid-svg-8T5XaxzkprBt4u25 .node polygon,#mermaid-svg-8T5XaxzkprBt4u25 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8T5XaxzkprBt4u25 .rough-node .label text,#mermaid-svg-8T5XaxzkprBt4u25 .node .label text,#mermaid-svg-8T5XaxzkprBt4u25 .image-shape .label,#mermaid-svg-8T5XaxzkprBt4u25 .icon-shape .label{text-anchor:middle;}#mermaid-svg-8T5XaxzkprBt4u25 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8T5XaxzkprBt4u25 .rough-node .label,#mermaid-svg-8T5XaxzkprBt4u25 .node .label,#mermaid-svg-8T5XaxzkprBt4u25 .image-shape .label,#mermaid-svg-8T5XaxzkprBt4u25 .icon-shape .label{text-align:center;}#mermaid-svg-8T5XaxzkprBt4u25 .node.clickable{cursor:pointer;}#mermaid-svg-8T5XaxzkprBt4u25 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8T5XaxzkprBt4u25 .arrowheadPath{fill:#333333;}#mermaid-svg-8T5XaxzkprBt4u25 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8T5XaxzkprBt4u25 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8T5XaxzkprBt4u25 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8T5XaxzkprBt4u25 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8T5XaxzkprBt4u25 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8T5XaxzkprBt4u25 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8T5XaxzkprBt4u25 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8T5XaxzkprBt4u25 .cluster text{fill:#333;}#mermaid-svg-8T5XaxzkprBt4u25 .cluster span{color:#333;}#mermaid-svg-8T5XaxzkprBt4u25 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8T5XaxzkprBt4u25 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8T5XaxzkprBt4u25 rect.text{fill:none;stroke-width:0;}#mermaid-svg-8T5XaxzkprBt4u25 .icon-shape,#mermaid-svg-8T5XaxzkprBt4u25 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8T5XaxzkprBt4u25 .icon-shape p,#mermaid-svg-8T5XaxzkprBt4u25 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8T5XaxzkprBt4u25 .icon-shape .label rect,#mermaid-svg-8T5XaxzkprBt4u25 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8T5XaxzkprBt4u25 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8T5XaxzkprBt4u25 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8T5XaxzkprBt4u25 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Java 并发 Bug
死锁
锁顺序不一致
循环等待
资源不可抢占
竞态条件
非原子操作
Check-Then-Act
Read-Modify-Write
内存可见性
工作内存缓存
指令重排序
缺少 volatile 或锁
线程池问题
参数配置不当
队列堆积
线程泄漏
异步编程
Future 阻塞
异常丢失
上下文丢失
性能问题
锁竞争
伪共享
上下文切换

一、死锁问题

1.1 什么是死锁

死锁是指两个或多个线程相互等待对方持有的资源,导致所有线程都无法继续执行。
#mermaid-svg-aM4M41YOrilLm3mN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aM4M41YOrilLm3mN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aM4M41YOrilLm3mN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aM4M41YOrilLm3mN .error-icon{fill:#552222;}#mermaid-svg-aM4M41YOrilLm3mN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aM4M41YOrilLm3mN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aM4M41YOrilLm3mN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aM4M41YOrilLm3mN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aM4M41YOrilLm3mN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aM4M41YOrilLm3mN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aM4M41YOrilLm3mN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aM4M41YOrilLm3mN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aM4M41YOrilLm3mN .marker.cross{stroke:#333333;}#mermaid-svg-aM4M41YOrilLm3mN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aM4M41YOrilLm3mN p{margin:0;}#mermaid-svg-aM4M41YOrilLm3mN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-aM4M41YOrilLm3mN .cluster-label text{fill:#333;}#mermaid-svg-aM4M41YOrilLm3mN .cluster-label span{color:#333;}#mermaid-svg-aM4M41YOrilLm3mN .cluster-label span p{background-color:transparent;}#mermaid-svg-aM4M41YOrilLm3mN .label text,#mermaid-svg-aM4M41YOrilLm3mN span{fill:#333;color:#333;}#mermaid-svg-aM4M41YOrilLm3mN .node rect,#mermaid-svg-aM4M41YOrilLm3mN .node circle,#mermaid-svg-aM4M41YOrilLm3mN .node ellipse,#mermaid-svg-aM4M41YOrilLm3mN .node polygon,#mermaid-svg-aM4M41YOrilLm3mN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aM4M41YOrilLm3mN .rough-node .label text,#mermaid-svg-aM4M41YOrilLm3mN .node .label text,#mermaid-svg-aM4M41YOrilLm3mN .image-shape .label,#mermaid-svg-aM4M41YOrilLm3mN .icon-shape .label{text-anchor:middle;}#mermaid-svg-aM4M41YOrilLm3mN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aM4M41YOrilLm3mN .rough-node .label,#mermaid-svg-aM4M41YOrilLm3mN .node .label,#mermaid-svg-aM4M41YOrilLm3mN .image-shape .label,#mermaid-svg-aM4M41YOrilLm3mN .icon-shape .label{text-align:center;}#mermaid-svg-aM4M41YOrilLm3mN .node.clickable{cursor:pointer;}#mermaid-svg-aM4M41YOrilLm3mN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aM4M41YOrilLm3mN .arrowheadPath{fill:#333333;}#mermaid-svg-aM4M41YOrilLm3mN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aM4M41YOrilLm3mN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aM4M41YOrilLm3mN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aM4M41YOrilLm3mN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aM4M41YOrilLm3mN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aM4M41YOrilLm3mN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aM4M41YOrilLm3mN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aM4M41YOrilLm3mN .cluster text{fill:#333;}#mermaid-svg-aM4M41YOrilLm3mN .cluster span{color:#333;}#mermaid-svg-aM4M41YOrilLm3mN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aM4M41YOrilLm3mN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aM4M41YOrilLm3mN rect.text{fill:none;stroke-width:0;}#mermaid-svg-aM4M41YOrilLm3mN .icon-shape,#mermaid-svg-aM4M41YOrilLm3mN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aM4M41YOrilLm3mN .icon-shape p,#mermaid-svg-aM4M41YOrilLm3mN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aM4M41YOrilLm3mN .icon-shape .label rect,#mermaid-svg-aM4M41YOrilLm3mN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aM4M41YOrilLm3mN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aM4M41YOrilLm3mN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aM4M41YOrilLm3mN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 持有
等待
持有
等待
被线程 1 占用
被线程 2 占用
线程 1
lockA
lockB
线程 2

java 复制代码
/**
 * 经典死锁示例
 */
 public class DeadLockDemo {
    
    private static final Object lockA = new Object();
    private static final Object lockB = new Object();
    
    public static void main(String[] args) {
        // 线程1:先获取lockA,再获取lockB
        Thread thread1 = new Thread(() -> {
            synchronized (lockA) {
                System.out.println("线程1获取到了lockA");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {}
                synchronized (lockB) {
                    System.out.println("线程1获取到了lockB");
                }
            }
        });
        
        // 线程2:先获取lockB,再获取lockA
        Thread thread2 = new Thread(() -> {
            synchronized (lockB) {
                System.out.println("线程2获取到了lockB");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {}
                synchronized (lockA) {
                    System.out.println("线程2获取到了lockA");
                }
            }
        });
        
        thread1.start();
        thread2.start();
        // 可能出现死锁:线程1持有lockA等待lockB,线程2持有lockB等待lockA
    }
 }

1.2 死锁的四个必要条件

  • 互斥条件:资源一次只能被一个线程持有
  • 持有并等待:线程持有资源的同时请求其他资源
  • 不可抢占:资源不能被强制从持有线程中抢占
  • 循环等待:存在线程资源的循环等待链

#mermaid-svg-1IWPJQI4IKy5VvH7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1IWPJQI4IKy5VvH7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1IWPJQI4IKy5VvH7 .error-icon{fill:#552222;}#mermaid-svg-1IWPJQI4IKy5VvH7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1IWPJQI4IKy5VvH7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1IWPJQI4IKy5VvH7 .marker.cross{stroke:#333333;}#mermaid-svg-1IWPJQI4IKy5VvH7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1IWPJQI4IKy5VvH7 p{margin:0;}#mermaid-svg-1IWPJQI4IKy5VvH7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1IWPJQI4IKy5VvH7 .cluster-label text{fill:#333;}#mermaid-svg-1IWPJQI4IKy5VvH7 .cluster-label span{color:#333;}#mermaid-svg-1IWPJQI4IKy5VvH7 .cluster-label span p{background-color:transparent;}#mermaid-svg-1IWPJQI4IKy5VvH7 .label text,#mermaid-svg-1IWPJQI4IKy5VvH7 span{fill:#333;color:#333;}#mermaid-svg-1IWPJQI4IKy5VvH7 .node rect,#mermaid-svg-1IWPJQI4IKy5VvH7 .node circle,#mermaid-svg-1IWPJQI4IKy5VvH7 .node ellipse,#mermaid-svg-1IWPJQI4IKy5VvH7 .node polygon,#mermaid-svg-1IWPJQI4IKy5VvH7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1IWPJQI4IKy5VvH7 .rough-node .label text,#mermaid-svg-1IWPJQI4IKy5VvH7 .node .label text,#mermaid-svg-1IWPJQI4IKy5VvH7 .image-shape .label,#mermaid-svg-1IWPJQI4IKy5VvH7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-1IWPJQI4IKy5VvH7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1IWPJQI4IKy5VvH7 .rough-node .label,#mermaid-svg-1IWPJQI4IKy5VvH7 .node .label,#mermaid-svg-1IWPJQI4IKy5VvH7 .image-shape .label,#mermaid-svg-1IWPJQI4IKy5VvH7 .icon-shape .label{text-align:center;}#mermaid-svg-1IWPJQI4IKy5VvH7 .node.clickable{cursor:pointer;}#mermaid-svg-1IWPJQI4IKy5VvH7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1IWPJQI4IKy5VvH7 .arrowheadPath{fill:#333333;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1IWPJQI4IKy5VvH7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1IWPJQI4IKy5VvH7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1IWPJQI4IKy5VvH7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1IWPJQI4IKy5VvH7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1IWPJQI4IKy5VvH7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1IWPJQI4IKy5VvH7 .cluster text{fill:#333;}#mermaid-svg-1IWPJQI4IKy5VvH7 .cluster span{color:#333;}#mermaid-svg-1IWPJQI4IKy5VvH7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1IWPJQI4IKy5VvH7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1IWPJQI4IKy5VvH7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-1IWPJQI4IKy5VvH7 .icon-shape,#mermaid-svg-1IWPJQI4IKy5VvH7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1IWPJQI4IKy5VvH7 .icon-shape p,#mermaid-svg-1IWPJQI4IKy5VvH7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1IWPJQI4IKy5VvH7 .icon-shape .label rect,#mermaid-svg-1IWPJQI4IKy5VvH7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1IWPJQI4IKy5VvH7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1IWPJQI4IKy5VvH7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1IWPJQI4IKy5VvH7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

互斥条件
持有并等待
不可抢占
循环等待
四个条件同时满足?
形成死锁
不会形成完整死锁闭环

1.3 死锁检测工具

java 复制代码
/**
 * 使用jstack检测死锁
 */
 public class DeadLockDetector {
    
    /**
     * 使用ThreadMXBean检测死锁
     */
     public static void detectDeadLock() {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        
        // 查找死锁线程
        long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
        
        if (deadlockedThreads != null && deadlockedThreads.length > 0) {
            System.out.println("检测到死锁!涉及的线程:");
            
            for (long threadId : deadlockedThreads) {
                ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId);
                System.out.println("线程名称:" + threadInfo.getThreadName());
                System.out.println("线程状态:" + threadInfo.getThreadState());
                
                // 打印死锁的Monitor
                LockInfo[] lockedMonitors = threadInfo.getLockedMonitors();
                for (LockInfo monitor : lockedMonitors) {
                    System.out.println("持有的Monitor:" + monitor);
                }
            }
        } else {
            System.out.println("未检测到死锁");
        }
     }
    
    /**
     * 定时检测死锁
     */
     public static void startMonitoring() {
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(
            () -> detectDeadLock(),
            0, 10, TimeUnit.SECONDS
        );
     }
  }

1.4 解决死锁的方法

java 复制代码
  /**
 * 方法1:固定加锁顺序
 */
 public class FixedLockOrder {
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();
    
    // 始终按照对象的hashCode顺序加锁
    public void method1() {
        // 计算hashCode并排序
        if (System.identityHashCode(lock1) < System.identityHashCode(lock2)) {
            synchronized (lock1) {
                synchronized (lock2) {
                    // 业务逻辑
                }
            }
        } else {
            synchronized (lock2) {
                synchronized (lock1) {
                    // 业务逻辑
                }
            }
        }
    }
 }
java 复制代码
/**
 * 方法2:使用tryLockwith超时
 */
 public class TryLockSolution {
    private final Lock lock1 = newReentrantLock();
    private final Lock lock2 = newReentrantLock();
    
    public void methodWithTimeout() {
        while (true) {
            // 尝试获取lock1
            if (lock1.tryLock()) {
                try {
                    // 尝试获取lock2
                    if (lock2.tryLock()) {
                        try {
                            // 业务逻辑
                            return;
                        } finally {
                            lock2.unlock();
                        }
                    }
                } finally {
                    lock1.unlock();
                }
            }
            
            // 等待后重试
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }
 }
java 复制代码
/**
 * 方法3:减少锁粒度,使用更细粒度的锁
 */
 public class ReduceLockScope {
    // 拆分为多个独立的锁
    private final Map<String, Object> cache1 = new ConcurrentHashMap<>();
    private final Map<String, Object> cache2 = new ConcurrentHashMap<>();
    private final Lock lock1 = newReentrantLock();
    private final Lock lock2 = newReentrantLock();
 }

二、竞态条件

2.1 什么是竞态条件

竞态条件是指程序的执行结果依赖于线程的执行顺序,多个线程对共享资源的访问顺序不确定。
线程 B 共享变量 count 线程 A 线程 B 共享变量 count 线程 A #mermaid-svg-gsT32vHbad9DOM2G{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gsT32vHbad9DOM2G .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gsT32vHbad9DOM2G .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gsT32vHbad9DOM2G .error-icon{fill:#552222;}#mermaid-svg-gsT32vHbad9DOM2G .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gsT32vHbad9DOM2G .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gsT32vHbad9DOM2G .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gsT32vHbad9DOM2G .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gsT32vHbad9DOM2G .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gsT32vHbad9DOM2G .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gsT32vHbad9DOM2G .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gsT32vHbad9DOM2G .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gsT32vHbad9DOM2G .marker.cross{stroke:#333333;}#mermaid-svg-gsT32vHbad9DOM2G svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gsT32vHbad9DOM2G p{margin:0;}#mermaid-svg-gsT32vHbad9DOM2G .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gsT32vHbad9DOM2G text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-gsT32vHbad9DOM2G .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gsT32vHbad9DOM2G .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-gsT32vHbad9DOM2G .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-gsT32vHbad9DOM2G .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-gsT32vHbad9DOM2G #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-gsT32vHbad9DOM2G .sequenceNumber{fill:white;}#mermaid-svg-gsT32vHbad9DOM2G #sequencenumber{fill:#333;}#mermaid-svg-gsT32vHbad9DOM2G #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-gsT32vHbad9DOM2G .messageText{fill:#333;stroke:none;}#mermaid-svg-gsT32vHbad9DOM2G .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gsT32vHbad9DOM2G .labelText,#mermaid-svg-gsT32vHbad9DOM2G .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-gsT32vHbad9DOM2G .loopText,#mermaid-svg-gsT32vHbad9DOM2G .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-gsT32vHbad9DOM2G .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gsT32vHbad9DOM2G .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-gsT32vHbad9DOM2G .noteText,#mermaid-svg-gsT32vHbad9DOM2G .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-gsT32vHbad9DOM2G .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gsT32vHbad9DOM2G .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gsT32vHbad9DOM2G .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gsT32vHbad9DOM2G .actorPopupMenu{position:absolute;}#mermaid-svg-gsT32vHbad9DOM2G .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-gsT32vHbad9DOM2G .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gsT32vHbad9DOM2G .actor-man circle,#mermaid-svg-gsT32vHbad9DOM2G line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-gsT32vHbad9DOM2G :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 预期结果是 2,实际可能是 1 读取 count = 0读取 count = 0写回 count = 1写回 count = 1

java 复制代码
/**
 * 竞态条件示例:计数器
 */
 public class RaceConditionDemo implementsRunnable {
    private int counter = 0;
    
    // 问题:++counter不是原子操作
    // 实际执行:读取counter -> 增加 -> 写入
    // 多个线程可能读到相同的值
    public void increment() {
        counter++;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            increment();
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        RaceConditionDemo demo = newRaceConditionDemo();
        
        Thread t1 = new Thread(demo);
        Thread t2 = new Thread(demo);
        
        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
        
        // 期望:20000
        // 实际:可能是任意值(小于20000)
        System.out.println(demo.counter);
    }
 }

2.2 常见的竞态条件模式

java 复制代码
 /**
 * 模式1:Check-Then-Act
 */
 public class CheckThenAct {
    privateMap<String, Object> cache = new ConcurrentHashMap<>();
    
    // 问题:检查和使用之间可能被其他线程修改
    publicObjectgetOrCreate(String key) {
        Object value = cache.get(key); // Check
        if (value == null) { // Then
            value = createValue(key); // Act
            cache.put(key, value);
        }
        return value;
    }
    
    // 解决方案:使用computeIfAbsent
    publicObjectgetOrCreateFixed(String key) {
        return cache.computeIfAbsent(key, this::createValue);
    }
 }
java 复制代码
/**
 * 模式2:Read-Modify-Write
 */
 public class ReadModifyWrite {
    private int value = 0;
    
    // 问题:读取、修改、写入不是原子操作
    public void increment() {
        int temp = value; // Read
        temp = temp + 1; // Modify
        value = temp; // Write
    }
    
    // 解决方案:使用原子类
    private AtomicInteger atomicValue = newAtomicInteger(0);
    
    public void incrementFixed() {
        atomicValue.incrementAndGet();
    }
 }

2.3 解决竞态条件

java 复制代码
 /**
 * 解决方案1:使用synchronized
 */
 public class SynchronizedSolution {
    private int counter = 0;
    
    publicsynchronizedvoidincrement() {
        counter++;
    }
    
    publicsynchronizedintget() {
        return counter;
    }
 }
java 复制代码
/**
 * 解决方案2:使用ReentrantLock
 */
 public class LockSolution {
    private int counter = 0;
    private final Lock lock = newReentrantLock();
    
    public void increment() {
        lock.lock();
        try {
            counter++;
        } finally {
            lock.unlock();
        }
    }
    
    publicintget() {
        lock.lock();
        try {
            return counter;
        } finally {
            lock.unlock();
        }
    }
 }
java 复制代码
/**
 * 解决方案3:使用原子类
 */
 public class AtomicSolution {
    private AtomicInteger counter = newAtomicInteger(0);
    
    public void increment() {
        counter.incrementAndGet();
    }
    
    publicintget() {
        return counter.get();
    }
 }

三、内存可见性问题

3.1 什么是内存可见性

内存可见性是指一个线程对共享变量的修改,其他线程能够及时看到。
#mermaid-svg-wYTNsCoD2ndQNId5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wYTNsCoD2ndQNId5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wYTNsCoD2ndQNId5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wYTNsCoD2ndQNId5 .error-icon{fill:#552222;}#mermaid-svg-wYTNsCoD2ndQNId5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wYTNsCoD2ndQNId5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wYTNsCoD2ndQNId5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wYTNsCoD2ndQNId5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wYTNsCoD2ndQNId5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wYTNsCoD2ndQNId5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wYTNsCoD2ndQNId5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wYTNsCoD2ndQNId5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wYTNsCoD2ndQNId5 .marker.cross{stroke:#333333;}#mermaid-svg-wYTNsCoD2ndQNId5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wYTNsCoD2ndQNId5 p{margin:0;}#mermaid-svg-wYTNsCoD2ndQNId5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wYTNsCoD2ndQNId5 .cluster-label text{fill:#333;}#mermaid-svg-wYTNsCoD2ndQNId5 .cluster-label span{color:#333;}#mermaid-svg-wYTNsCoD2ndQNId5 .cluster-label span p{background-color:transparent;}#mermaid-svg-wYTNsCoD2ndQNId5 .label text,#mermaid-svg-wYTNsCoD2ndQNId5 span{fill:#333;color:#333;}#mermaid-svg-wYTNsCoD2ndQNId5 .node rect,#mermaid-svg-wYTNsCoD2ndQNId5 .node circle,#mermaid-svg-wYTNsCoD2ndQNId5 .node ellipse,#mermaid-svg-wYTNsCoD2ndQNId5 .node polygon,#mermaid-svg-wYTNsCoD2ndQNId5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wYTNsCoD2ndQNId5 .rough-node .label text,#mermaid-svg-wYTNsCoD2ndQNId5 .node .label text,#mermaid-svg-wYTNsCoD2ndQNId5 .image-shape .label,#mermaid-svg-wYTNsCoD2ndQNId5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-wYTNsCoD2ndQNId5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wYTNsCoD2ndQNId5 .rough-node .label,#mermaid-svg-wYTNsCoD2ndQNId5 .node .label,#mermaid-svg-wYTNsCoD2ndQNId5 .image-shape .label,#mermaid-svg-wYTNsCoD2ndQNId5 .icon-shape .label{text-align:center;}#mermaid-svg-wYTNsCoD2ndQNId5 .node.clickable{cursor:pointer;}#mermaid-svg-wYTNsCoD2ndQNId5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wYTNsCoD2ndQNId5 .arrowheadPath{fill:#333333;}#mermaid-svg-wYTNsCoD2ndQNId5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wYTNsCoD2ndQNId5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wYTNsCoD2ndQNId5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wYTNsCoD2ndQNId5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wYTNsCoD2ndQNId5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wYTNsCoD2ndQNId5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wYTNsCoD2ndQNId5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wYTNsCoD2ndQNId5 .cluster text{fill:#333;}#mermaid-svg-wYTNsCoD2ndQNId5 .cluster span{color:#333;}#mermaid-svg-wYTNsCoD2ndQNId5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wYTNsCoD2ndQNId5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wYTNsCoD2ndQNId5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-wYTNsCoD2ndQNId5 .icon-shape,#mermaid-svg-wYTNsCoD2ndQNId5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wYTNsCoD2ndQNId5 .icon-shape p,#mermaid-svg-wYTNsCoD2ndQNId5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wYTNsCoD2ndQNId5 .icon-shape .label rect,#mermaid-svg-wYTNsCoD2ndQNId5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wYTNsCoD2ndQNId5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wYTNsCoD2ndQNId5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wYTNsCoD2ndQNId5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 线程 B
线程 A
未及时刷新
未及时同步
工作内存 A
修改共享变量 flag=false
工作内存 B
循环读取 flag
主内存

共享变量 flag
volatile / synchronized / Lock

建立可见性保障

java 复制代码
/**
 * 内存可见性问题
 */
 public class VisibilityDemo {
    privateboolean flag = true;
    private int counter = 0;
    
    // 线程1:写入flag
    public void writer() {
        counter = 1; // 步骤1
        flag = false; // 步骤2
    }
    
    // 线程2:读取flag
    public void reader() {
        while (flag) { // 步骤3
            // 等待
        }
        System.out.println(counter); // 步骤4
    }
    
    // 问题:线程2可能永远看不到flag的最新值
    // 原因:CPU缓存 vs 主内存
 }
java 复制代码
/**
 * 解决方案1:使用volatile
 */
 public class VolatileSolution {
    private volatile boolean flag = true;
    private volatile int counter = 0;
    
    // volatile保证:
    // 1. 写操作立即刷新到主内存
    // 2. 读操作从主内存读取
    // 3. 禁止指令重排序(内存屏障)
 }
java 复制代码
/**
 * 解决方案2:使用synchronized
 */
 public class SynchronizedVisibility {
    privateboolean flag = true;
    private int counter = 0;
    
    publicsynchronizedvoidwriter() {
        counter = 1;
        flag = false;
    }
    
    publicsynchronizedvoidreader() {
        while (!flag) {
            // 等待
        }
        System.out.println(counter);
    }
 }

3.2 volatile 的深入理解

java 复制代码
 /**
 * volatile的三重语义
 */
 public class VolatileUnderstanding {
    
    // 1. 可见性
    // 每次读取volatile变量都会从主内存读取
    // 每次写入volatile变量都会立即刷新到主内存
    volatileboolean ready;
    volatileint number;
    
    // 2. 禁止指令重排序
    // volatile写操作之前的操作不会被重排序到volatile写之后
    // volatile读操作之后的操作不会被重排序到volatile读之前
    
    // 示例:
    // volatile写之前的操作 a=1; b=2;
    // volatile写:flag=true;
    // volatile读:if (flag) { System.out.println(b); }
    // 保证输出2而不是0
    
    // 3. 不保证原子性
    // 下面操作不是原子的
    volatileint counter = 0;
    // counter++ 实际是:读取->修改->写入
    // 多个线程执行会导致数据丢失
 }

四、并发容器问题

4.1 ConcurrentHashMap 的注意事项

java 复制代码
 /**
 * ConcurrentHashMap的并发问题
 */
 public class ConcurrentHashMapPitfalls {
    
    // 问题1:复合操作不是原子的
    ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
    
    // 错误的复合操作
    public void wrongCompoundOps() {
        // 先检查再操作 - 不是原子
        if (map.containsKey("key")) {
            map.get("key"); // 可能已被其他线程删除
        }
        
        // 迭代过程中修改 - ConcurrentModificationException
        for (String key : map.keySet()) {
            // 其他线程可能修改map
        }
    }
    
    // 正确的做法:使用原子方法
    public void correctOps() {
        // 使用computeIfAbsent
        map.computeIfAbsent("key", k -> 1);
        
        // 使用putIfAbsent
        map.putIfAbsent("key", 1);
        
        // 使用replace
        map.replace("key", 1, 2);
        
        // 使用批量操作
        map.forEach(1, (k, v) -> System.out.println(k + ":" + v));
    }
 }

4.2 CopyOnWriteArrayList 的注意事项

java 复制代码
 /**
 * CopyOnWriteArrayList的适用场景
 */
 public class CopyOnWritePitfalls {
    
    // 适用:读多写少的场景
    private CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
    
    // 问题:迭代器弱一致性
    public void iteratorIssue() {
        list.add("a");
        list.add("b");
        
        Iterator<String> iterator = list.iterator();
        list.add("c"); // 修改后,迭代器不会反映新元素
        
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
            // 输出:a, b(不包含c)
        }
    }
    
    // 问题:迭代器不支持remove操作
    public void removeIssue() {
        list.add("a");
        list.add("b");
        
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            iterator.next();
            iterator.remove(); // 抛出UnsupportedOperationException
        }
    }
 }

五、线程池问题

5.1 线程池配置不当

#mermaid-svg-1cXZK2vefuDbVfrg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1cXZK2vefuDbVfrg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1cXZK2vefuDbVfrg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1cXZK2vefuDbVfrg .error-icon{fill:#552222;}#mermaid-svg-1cXZK2vefuDbVfrg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1cXZK2vefuDbVfrg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1cXZK2vefuDbVfrg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1cXZK2vefuDbVfrg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1cXZK2vefuDbVfrg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1cXZK2vefuDbVfrg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1cXZK2vefuDbVfrg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1cXZK2vefuDbVfrg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1cXZK2vefuDbVfrg .marker.cross{stroke:#333333;}#mermaid-svg-1cXZK2vefuDbVfrg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1cXZK2vefuDbVfrg p{margin:0;}#mermaid-svg-1cXZK2vefuDbVfrg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1cXZK2vefuDbVfrg .cluster-label text{fill:#333;}#mermaid-svg-1cXZK2vefuDbVfrg .cluster-label span{color:#333;}#mermaid-svg-1cXZK2vefuDbVfrg .cluster-label span p{background-color:transparent;}#mermaid-svg-1cXZK2vefuDbVfrg .label text,#mermaid-svg-1cXZK2vefuDbVfrg span{fill:#333;color:#333;}#mermaid-svg-1cXZK2vefuDbVfrg .node rect,#mermaid-svg-1cXZK2vefuDbVfrg .node circle,#mermaid-svg-1cXZK2vefuDbVfrg .node ellipse,#mermaid-svg-1cXZK2vefuDbVfrg .node polygon,#mermaid-svg-1cXZK2vefuDbVfrg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1cXZK2vefuDbVfrg .rough-node .label text,#mermaid-svg-1cXZK2vefuDbVfrg .node .label text,#mermaid-svg-1cXZK2vefuDbVfrg .image-shape .label,#mermaid-svg-1cXZK2vefuDbVfrg .icon-shape .label{text-anchor:middle;}#mermaid-svg-1cXZK2vefuDbVfrg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1cXZK2vefuDbVfrg .rough-node .label,#mermaid-svg-1cXZK2vefuDbVfrg .node .label,#mermaid-svg-1cXZK2vefuDbVfrg .image-shape .label,#mermaid-svg-1cXZK2vefuDbVfrg .icon-shape .label{text-align:center;}#mermaid-svg-1cXZK2vefuDbVfrg .node.clickable{cursor:pointer;}#mermaid-svg-1cXZK2vefuDbVfrg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1cXZK2vefuDbVfrg .arrowheadPath{fill:#333333;}#mermaid-svg-1cXZK2vefuDbVfrg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1cXZK2vefuDbVfrg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1cXZK2vefuDbVfrg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1cXZK2vefuDbVfrg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1cXZK2vefuDbVfrg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1cXZK2vefuDbVfrg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1cXZK2vefuDbVfrg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1cXZK2vefuDbVfrg .cluster text{fill:#333;}#mermaid-svg-1cXZK2vefuDbVfrg .cluster span{color:#333;}#mermaid-svg-1cXZK2vefuDbVfrg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1cXZK2vefuDbVfrg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1cXZK2vefuDbVfrg rect.text{fill:none;stroke-width:0;}#mermaid-svg-1cXZK2vefuDbVfrg .icon-shape,#mermaid-svg-1cXZK2vefuDbVfrg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1cXZK2vefuDbVfrg .icon-shape p,#mermaid-svg-1cXZK2vefuDbVfrg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1cXZK2vefuDbVfrg .icon-shape .label rect,#mermaid-svg-1cXZK2vefuDbVfrg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1cXZK2vefuDbVfrg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1cXZK2vefuDbVfrg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1cXZK2vefuDbVfrg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是





提交任务
核心线程是否空闲?
核心线程执行
工作队列是否已满?
进入阻塞队列
是否可创建非核心线程?
创建临时线程执行
触发拒绝策略
线程池消费队列任务

java 复制代码
 /**
 * 线程池问题
 */
 public class ThreadPoolPitfalls {
    
    // 问题1:使用 Executors 的不恰当方法
    // FixedThreadPool和SingleThreadPool使用无界队列,可能导致OOM
    ExecutorService badPool1 = Executors.newFixedThreadPool(100); // 队列 Integer.MAX_VALUE
    ExecutorService badPool2 = Executors.newSingleThreadExecutor();
    
    // 正确做法:使用ThreadPoolExecutor并指定队列大小
    ExecutorService goodPool = new ThreadPoolExecutor(
        10, 100,
        60L, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(1000), // 有界队列
        new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
    );
    
    // 问题2:线程池拒绝策略不当
    // AbortPolicy:直接抛异常
    // DiscardPolicy:静默丢弃
    // DiscardOldestPolicy:丢弃最老的任务
    // CallerRunsPolicy:由调用线程执行
    
    // 问题3:共享线程池导致阻塞
    public void sharedPoolIssue() {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        
        // 在线程池的任务中使用阻塞操作,可能导致死锁
        pool.submit(() -> {
            // 这是一个可能死锁的操作
            try {
                pool.submit(() -> {
                    // 子任务也在等待
                }).get(); // 等待完成
            } catch (Exception e) {}
        });
    }
 }

5.2 线程泄漏

java 复制代码
 /**
 * 线程泄漏问题
 */
 public class ThreadLeakExample {
    private final ExecutorService executor = Executors.newFixedThreadPool(10);
    private final ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    // 问题1:ThreadLocal内存泄漏
    public void threadLocalLeak() {
        for (int i = 0; i < 100; i++) {
            executor.submit(() -> {
                threadLocal.set(Thread.currentThread().getName());
                // 忘记清理
                // threadLocal.remove();
            });
        }
    }
    
    // 解决:使用完立即remove
    public void threadLocalFixed() {
        executor.submit(() -> {
            try {
                threadLocal.set(Thread.currentThread().getName());
                // 业务逻辑
            } finally {
                threadLocal.remove(); // 关键
            }
        });
    }
 }

六、异步编程问题

6.1 Future 的坑

异步任务 线程池 主线程 异步任务 线程池 主线程 #mermaid-svg-d1FtuuryPgfZ1vHx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-d1FtuuryPgfZ1vHx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d1FtuuryPgfZ1vHx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d1FtuuryPgfZ1vHx .error-icon{fill:#552222;}#mermaid-svg-d1FtuuryPgfZ1vHx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d1FtuuryPgfZ1vHx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d1FtuuryPgfZ1vHx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d1FtuuryPgfZ1vHx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d1FtuuryPgfZ1vHx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d1FtuuryPgfZ1vHx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d1FtuuryPgfZ1vHx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d1FtuuryPgfZ1vHx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d1FtuuryPgfZ1vHx .marker.cross{stroke:#333333;}#mermaid-svg-d1FtuuryPgfZ1vHx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d1FtuuryPgfZ1vHx p{margin:0;}#mermaid-svg-d1FtuuryPgfZ1vHx .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-d1FtuuryPgfZ1vHx text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-d1FtuuryPgfZ1vHx .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-d1FtuuryPgfZ1vHx .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-d1FtuuryPgfZ1vHx .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-d1FtuuryPgfZ1vHx .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-d1FtuuryPgfZ1vHx #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-d1FtuuryPgfZ1vHx .sequenceNumber{fill:white;}#mermaid-svg-d1FtuuryPgfZ1vHx #sequencenumber{fill:#333;}#mermaid-svg-d1FtuuryPgfZ1vHx #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-d1FtuuryPgfZ1vHx .messageText{fill:#333;stroke:none;}#mermaid-svg-d1FtuuryPgfZ1vHx .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-d1FtuuryPgfZ1vHx .labelText,#mermaid-svg-d1FtuuryPgfZ1vHx .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-d1FtuuryPgfZ1vHx .loopText,#mermaid-svg-d1FtuuryPgfZ1vHx .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-d1FtuuryPgfZ1vHx .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-d1FtuuryPgfZ1vHx .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-d1FtuuryPgfZ1vHx .noteText,#mermaid-svg-d1FtuuryPgfZ1vHx .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-d1FtuuryPgfZ1vHx .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-d1FtuuryPgfZ1vHx .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-d1FtuuryPgfZ1vHx .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-d1FtuuryPgfZ1vHx .actorPopupMenu{position:absolute;}#mermaid-svg-d1FtuuryPgfZ1vHx .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-d1FtuuryPgfZ1vHx .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-d1FtuuryPgfZ1vHx .actor-man circle,#mermaid-svg-d1FtuuryPgfZ1vHx line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-d1FtuuryPgfZ1vHx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alt任务执行慢或阻塞任务抛异常 submit(task)执行任务future.get()主线程被阻塞异常被封装get() 时才感知 ExecutionException

java 复制代码
 /**
 * Future常见问题
 */
 public class FuturePitfalls {
    private final ExecutorService executor = Executors.newFixedThreadPool(10);
    
    // 问题1:get()阻塞导致线程阻塞
    public void getBlocking() {
        Future<String> future = executor.submit(() -> {
            Thread.sleep(10000);
            return "result";
        });
        
        // 阻塞等待,可能导致线程池耗尽
        String result = future.get(); // 阻塞!
    }
    
    // 问题2:未正确处理异常
    public void exceptionNotHandled() {
        Future<String> future = executor.submit(() -> {
            throw new RuntimeException("error");
        });
        
        // 如果不调用get(),异常会被吞噬
        // future.get(); // 可以看到异常
    }
    
    // 正确做法1:使用回调
    public void callbackApproach() {
        CompletableFuture<String> future = CompletableFuture
            .supplyAsync(() -> "result", executor)
            .thenApply(result -> result.toUpperCase())
            .exceptionally(ex -> {
                System.err.println("Error: " + ex.getMessage());
                return "default";
            });
    }
    
    // 正确做法2:使用超时
    public void timeoutApproach() {
        Future<String> future = executor.submit(() -> {
            Thread.sleep(10000);
            return "result";
        });
        
        try {
            String result = future.get(5, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            future.cancel(true);
        } catch (Exception e) {}
    }
 }

6.2 异步调用链问题

java 复制代码
 /**
 * 异步调用链问题
 */
 public class AsyncChainPitfalls {
    private final ExecutorService executor = Executors.newFixedThreadPool(10);
    
    // 问题1:线程上下文丢失
    public void contextLoss() {
        ThreadLocal<String> context = new ThreadLocal<>();
        context.set("main-context");
        
        executor.submit(() -> {
            // 子线程中无法获取主线程的context
            System.out.println(context.get()); // null
        });
    }
    
    // 问题2:异常传播丢失
    public void exceptionLoss() {
        executor.submit(() -> {
            throw new RuntimeException("error in async");
        });
        // 异常未处理,线程终止但不抛向主线程
    }
    
    // 正确做法:使用InheritableThreadLocal或上下文传递
    public void contextPropagation() {
        ExecutorService contextualExecutor =
            Contexts.wrap(Executors.newFixedThreadPool(10));
        
        // 或者使用阿里开源的TransmittableThreadLocal
    }
 }

七、性能问题

7.1 锁竞争优化

java 复制代码
 /**
 * 锁竞争优化策略
 */
 public class LockContentionOptimization {
    
    // 策略1:减少锁持有时间
    public void reduceLockTime() {
        // 错误:长时间持有锁
        synchronized (this) {
            // 业务处理
            // ...
            // 数据库操作(耗时)
            // ...
            // 网络调用(耗时)
        }
        
        // 正确:快速释放锁
        Object data;
        synchronized (this) {
            data = this.data; // 只获取数据
        }
        // 耗时操作在锁外进行
        process(data);
    }
    
    // 策略2:减小锁粒度
    private final Map<String, Object> map1 = new ConcurrentHashMap<>();
    private final Map<String, Object> map2 = new ConcurrentHashMap<>();
    
    // 替代单一全局锁
    // 将数据分片到多个map
 }

7.2 伪共享问题

java 复制代码
 /**
 * 伪共享问题
 */
 public class FalseSharingProblem {
    
    // 问题:LongAdder的分段设计解决伪共享
    // 每个Segment有独立的计数器
    // 避免多个线程竞争同一缓存行
    
    // 解决方案:缓存行填充
    public static class PaddedLong {
        private long p1, p2, p3, p4, p5, p6, p7;
        public volatile long value;
        private long p8, p9, p10, p11, p12, p13, p14;
    }
    
    // Java 8+ 可以使用 @Contended 注解
    // @Contended
    // public class ContendedLong {
    // public volatile long value;
    // }
 }

八、调试与排查技巧

8.1 常用诊断工具

#mermaid-svg-rUkUIIydjY2tTs2c{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rUkUIIydjY2tTs2c .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rUkUIIydjY2tTs2c .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rUkUIIydjY2tTs2c .error-icon{fill:#552222;}#mermaid-svg-rUkUIIydjY2tTs2c .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rUkUIIydjY2tTs2c .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rUkUIIydjY2tTs2c .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rUkUIIydjY2tTs2c .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rUkUIIydjY2tTs2c .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rUkUIIydjY2tTs2c .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rUkUIIydjY2tTs2c .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rUkUIIydjY2tTs2c .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rUkUIIydjY2tTs2c .marker.cross{stroke:#333333;}#mermaid-svg-rUkUIIydjY2tTs2c svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rUkUIIydjY2tTs2c p{margin:0;}#mermaid-svg-rUkUIIydjY2tTs2c .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rUkUIIydjY2tTs2c .cluster-label text{fill:#333;}#mermaid-svg-rUkUIIydjY2tTs2c .cluster-label span{color:#333;}#mermaid-svg-rUkUIIydjY2tTs2c .cluster-label span p{background-color:transparent;}#mermaid-svg-rUkUIIydjY2tTs2c .label text,#mermaid-svg-rUkUIIydjY2tTs2c span{fill:#333;color:#333;}#mermaid-svg-rUkUIIydjY2tTs2c .node rect,#mermaid-svg-rUkUIIydjY2tTs2c .node circle,#mermaid-svg-rUkUIIydjY2tTs2c .node ellipse,#mermaid-svg-rUkUIIydjY2tTs2c .node polygon,#mermaid-svg-rUkUIIydjY2tTs2c .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rUkUIIydjY2tTs2c .rough-node .label text,#mermaid-svg-rUkUIIydjY2tTs2c .node .label text,#mermaid-svg-rUkUIIydjY2tTs2c .image-shape .label,#mermaid-svg-rUkUIIydjY2tTs2c .icon-shape .label{text-anchor:middle;}#mermaid-svg-rUkUIIydjY2tTs2c .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rUkUIIydjY2tTs2c .rough-node .label,#mermaid-svg-rUkUIIydjY2tTs2c .node .label,#mermaid-svg-rUkUIIydjY2tTs2c .image-shape .label,#mermaid-svg-rUkUIIydjY2tTs2c .icon-shape .label{text-align:center;}#mermaid-svg-rUkUIIydjY2tTs2c .node.clickable{cursor:pointer;}#mermaid-svg-rUkUIIydjY2tTs2c .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rUkUIIydjY2tTs2c .arrowheadPath{fill:#333333;}#mermaid-svg-rUkUIIydjY2tTs2c .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rUkUIIydjY2tTs2c .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rUkUIIydjY2tTs2c .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rUkUIIydjY2tTs2c .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rUkUIIydjY2tTs2c .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rUkUIIydjY2tTs2c .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rUkUIIydjY2tTs2c .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rUkUIIydjY2tTs2c .cluster text{fill:#333;}#mermaid-svg-rUkUIIydjY2tTs2c .cluster span{color:#333;}#mermaid-svg-rUkUIIydjY2tTs2c div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rUkUIIydjY2tTs2c .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rUkUIIydjY2tTs2c rect.text{fill:none;stroke-width:0;}#mermaid-svg-rUkUIIydjY2tTs2c .icon-shape,#mermaid-svg-rUkUIIydjY2tTs2c .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rUkUIIydjY2tTs2c .icon-shape p,#mermaid-svg-rUkUIIydjY2tTs2c .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rUkUIIydjY2tTs2c .icon-shape .label rect,#mermaid-svg-rUkUIIydjY2tTs2c .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rUkUIIydjY2tTs2c .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rUkUIIydjY2tTs2c .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rUkUIIydjY2tTs2c :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 线程卡住
CPU 高
数据不一致
线程池堆积
发现并发异常

卡死 / 数据错乱 / CPU 飙高
问题类型判断
jstack / Arthas thread
top + jstack / async-profiler
代码审查共享变量与锁
查看队列长度 / 活跃线程 / 拒绝策略
定位阻塞点或死锁链
定位热点方法与锁竞争
检查原子性 / 可见性 / 有序性
调整线程池参数或降级策略
修复并压测验证

java 复制代码
 /**
 * 并发问题诊断工具
 */
 public class ConcurrencyDiagnostics {
    
    // 1. jstack - 打印线程堆栈
    // jstack <pid>
    
    // 2. jconsole - 监控线程状态
    // 3. VisualVM - 可视化分析
    // 4. Async-profiler - 性能分析
    
    // 5. 使用Arthas
    // thread - 查看线程堆栈
    // thread -b - 查找阻塞的线程
    // thread --state WAITING - 查看等待状态的线程
 }

8.2 代码审查要点

java 复制代码
 /**
 * 并发代码审查清单
 */
 public class ConcurrencyChecklist {
    
    // 1. 共享可变状态
    // - 是否有多个线程访问共享变量?
    // - 是否使用了正确的同步机制?
    
    // 2. 对象逸出
    // - 是否在构造过程中逸出了this引用?
    // - 是否有内部类隐式持有外部类引用?
    
    // 3. 线程安全委托
    // - 是否正确使用了线程安全类?
    // - 是否误用了非线程安全类?
    
    // 4. 死锁风险
    // - 多个锁的获取顺序是否一致?
    // - 是否有tryLock超时机制?
    
    // 5. 资源管理
    // - 线程池是否正确关闭?
    // - ThreadLocal是否正确清理?
 }

九、面试高频问题

#mermaid-svg-dWHEu5W4TebYyLMM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dWHEu5W4TebYyLMM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dWHEu5W4TebYyLMM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dWHEu5W4TebYyLMM .error-icon{fill:#552222;}#mermaid-svg-dWHEu5W4TebYyLMM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dWHEu5W4TebYyLMM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dWHEu5W4TebYyLMM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dWHEu5W4TebYyLMM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dWHEu5W4TebYyLMM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dWHEu5W4TebYyLMM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dWHEu5W4TebYyLMM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dWHEu5W4TebYyLMM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dWHEu5W4TebYyLMM .marker.cross{stroke:#333333;}#mermaid-svg-dWHEu5W4TebYyLMM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dWHEu5W4TebYyLMM p{margin:0;}#mermaid-svg-dWHEu5W4TebYyLMM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-dWHEu5W4TebYyLMM .cluster-label text{fill:#333;}#mermaid-svg-dWHEu5W4TebYyLMM .cluster-label span{color:#333;}#mermaid-svg-dWHEu5W4TebYyLMM .cluster-label span p{background-color:transparent;}#mermaid-svg-dWHEu5W4TebYyLMM .label text,#mermaid-svg-dWHEu5W4TebYyLMM span{fill:#333;color:#333;}#mermaid-svg-dWHEu5W4TebYyLMM .node rect,#mermaid-svg-dWHEu5W4TebYyLMM .node circle,#mermaid-svg-dWHEu5W4TebYyLMM .node ellipse,#mermaid-svg-dWHEu5W4TebYyLMM .node polygon,#mermaid-svg-dWHEu5W4TebYyLMM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dWHEu5W4TebYyLMM .rough-node .label text,#mermaid-svg-dWHEu5W4TebYyLMM .node .label text,#mermaid-svg-dWHEu5W4TebYyLMM .image-shape .label,#mermaid-svg-dWHEu5W4TebYyLMM .icon-shape .label{text-anchor:middle;}#mermaid-svg-dWHEu5W4TebYyLMM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dWHEu5W4TebYyLMM .rough-node .label,#mermaid-svg-dWHEu5W4TebYyLMM .node .label,#mermaid-svg-dWHEu5W4TebYyLMM .image-shape .label,#mermaid-svg-dWHEu5W4TebYyLMM .icon-shape .label{text-align:center;}#mermaid-svg-dWHEu5W4TebYyLMM .node.clickable{cursor:pointer;}#mermaid-svg-dWHEu5W4TebYyLMM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dWHEu5W4TebYyLMM .arrowheadPath{fill:#333333;}#mermaid-svg-dWHEu5W4TebYyLMM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dWHEu5W4TebYyLMM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dWHEu5W4TebYyLMM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dWHEu5W4TebYyLMM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dWHEu5W4TebYyLMM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dWHEu5W4TebYyLMM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dWHEu5W4TebYyLMM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dWHEu5W4TebYyLMM .cluster text{fill:#333;}#mermaid-svg-dWHEu5W4TebYyLMM .cluster span{color:#333;}#mermaid-svg-dWHEu5W4TebYyLMM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dWHEu5W4TebYyLMM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dWHEu5W4TebYyLMM rect.text{fill:none;stroke-width:0;}#mermaid-svg-dWHEu5W4TebYyLMM .icon-shape,#mermaid-svg-dWHEu5W4TebYyLMM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dWHEu5W4TebYyLMM .icon-shape p,#mermaid-svg-dWHEu5W4TebYyLMM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dWHEu5W4TebYyLMM .icon-shape .label rect,#mermaid-svg-dWHEu5W4TebYyLMM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dWHEu5W4TebYyLMM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dWHEu5W4TebYyLMM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dWHEu5W4TebYyLMM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否



线程安全类设计
识别共享可变状态
定义不变约束
状态是否需要并发修改?
优先不可变对象 / 线程封闭
操作是否简单计数或 CAS 可表达?
Atomic / LongAdder / 并发容器
synchronized / Lock / ReadWriteLock
控制锁粒度与加锁顺序
补充可见性与异常处理
文档说明线程安全策略

Q1: 如何排查死锁?

  • 使用 jstack 查看线程堆栈,找到互相等待的线程
  • 使用 ThreadMXBeanfindDeadlockedThreads 方法
  • 查看代码中的加锁顺序
  • 使用 Arthasthread -b 命令

Q2: volatilesynchronized 的区别?

特性 volatile synchronized
作用 可见性、有序性 可见性、有序性、原子性
性能 更好 较差
使用场景 标记位、状态位 复杂业务逻辑

Q3: ConcurrentHashMap 为什么高效?

  • 内部使用分段锁,减少锁竞争
  • 使用 CAS 操作,减少阻塞
  • 读操作无锁(volatile)
  • 键值对不允许为 null

Q4: 什么是伪共享?

CPU 缓存行是 64 字节,当多个变量共享同一缓存行,一个线程修改会导致其他线程的缓存行失效,即使它们访问的是不同变量。

Q5: 如何设计线程安全的类?

  • 识别共享可变状态
  • 确定状态变量的不变约束
  • 设计对象状态修改的并发策略
  • 使用适当的同步机制
  • 编写文档说明线程安全性

并发 Bug 往往在生产环境中才会暴露,养成良好的并发编程习惯,使用正确的同步机制,是避免并发问题的关键。

相关推荐
极客先躯1 小时前
高级java每日一道面试题-2026年02月09日-实战篇[Docker]-Docker 容器有哪些安全风险?如何缓解?
java·运维·网络·安全·docker·容器
_Aaron___2 小时前
MyBatis 动态排序别乱用 ${}:ORDER BY 的安全写法
java·spring·mybatis
摇滚侠2 小时前
SpringMVC 入门到实战 HttpMessageConverter 65-74
java·后端·spring·intellij-idea
逢君学术论文AI写作2 小时前
Java第24课:会话技术CookieSession
java·开发语言
小小编程路2 小时前
字符串转数字时,可能会遇到哪些问题?
java·开发语言·算法
许彰午2 小时前
责任链模式实战——同一个框架里的两种链
java·开发语言·责任链模式
寻道码路2 小时前
LangChain4j Java AI 应用开发实战(十四):手写 RAG 全流程 - 深入理解每个环节
java·开发语言·人工智能·ai
云烟成雨TD2 小时前
Agent Scope Java 2.x 系列【1】核心架构
java·人工智能·agent
愛~杦辷个訾2 小时前
Java Springboot使用阿里云oss对图片进行等质量压缩,转换成webp格式的压缩图。
java·spring boot·阿里云·oss