<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>多线程 on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Wed, 28 Mar 2018 14:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>Java 高并发编程实战：同步工具、锁与线程池</title>
      <link>https://ftmao.com/blog/posts/java-concurrency-guide/</link>
      <pubDate>Wed, 28 Mar 2018 14:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/java-concurrency-guide/</guid>
      <description>&lt;h1 id=&#34;java-高并发编程实战同步工具锁与线程池&#34;&gt;Java 高并发编程实战：同步工具、锁与线程池&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;高并发程序的核心不是“让线程跑得多快”，而是&lt;strong&gt;让多个线程在共享可变状态下安全、可预期地协作&lt;/strong&gt;。JDK 的 &lt;code&gt;java.util.concurrent&lt;/code&gt;（JUC）包已经为我们提供了大量经过打磨的同步工具，善用它们比手写 &lt;code&gt;wait/notify&lt;/code&gt; 要可靠得多。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一高层次思想并发编程在解决什么问题&#34;&gt;一、高层次思想：并发编程在解决什么问题？&lt;/h2&gt;
&lt;p&gt;并发编程的本质是&lt;strong&gt;约束&lt;/strong&gt;：当多个线程访问同一组可变资源时，通过某种机制保证以下三件事至少满足其一：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;互斥&lt;/strong&gt;：同一时刻只有一个线程能访问临界区。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可见性&lt;/strong&gt;：一个线程修改的状态，其他线程能正确看到。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;有序性&lt;/strong&gt;：指令不会被编译器或 CPU 乱序到破坏程序语义。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[共享可变状态] --&amp;gt;|互斥| B[锁 / 信号量]
    A --&amp;gt;|可见性| C[volatile / happens-before]
    A --&amp;gt;|有序性| D[内存屏障 / 同步原语]
    B --&amp;gt; E[正确的并发程序]
    C --&amp;gt; E
    D --&amp;gt; E&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;首选策略金字塔&lt;/strong&gt;（从推荐到不推荐）：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[不可变对象 &amp;amp; 线程封闭] --&amp;gt; B[JUC 并发集合 / 线程池]
    B --&amp;gt; C[高级同步工具 CountDownLatch Semaphore 等]
    C --&amp;gt; D[ReentrantLock &amp;amp; Condition]
    D --&amp;gt; E[synchronized]
    E --&amp;gt; F[手写 wait/notify]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #1&lt;/strong&gt;：不到万不得已不要手写 &lt;code&gt;wait/notify&lt;/code&gt;，极容易写出遗漏 &lt;code&gt;notify&lt;/code&gt;、虚假唤醒、持锁休眠等问题。JUC 工具类已经帮你封装好了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二线程状态与原语对照&#34;&gt;二、线程状态与原语对照&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;方法&lt;/th&gt;
					&lt;th&gt;调用者&lt;/th&gt;
					&lt;th&gt;是否释放锁&lt;/th&gt;
					&lt;th&gt;进入状态&lt;/th&gt;
					&lt;th&gt;唤醒条件&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Thread.sleep(ms)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;当前线程&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TIMED_WAITING&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;时间到&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Thread.yield()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;当前线程&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RUNNABLE&lt;/code&gt;（让出 CPU）&lt;/td&gt;
					&lt;td&gt;OS 调度&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;t.join()&lt;/code&gt; / &lt;code&gt;t.join(ms)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;当前线程等 t&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;WAITING&lt;/code&gt; / &lt;code&gt;TIMED_WAITING&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;t 结束或超时&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;obj.wait()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;当前线程&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;是&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;WAITING&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;notify/notifyAll&lt;/code&gt; 或超时&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;obj.notify()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;当前线程&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;—&lt;/td&gt;
					&lt;td&gt;唤醒一个等待线程&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;stateDiagram-v2
    [*] --&amp;gt; 新建: new Thread()
    新建 --&amp;gt; 就绪: start()
    就绪 --&amp;gt; 运行: 调度
    运行 --&amp;gt; 就绪: yield / 时间片到
    运行 --&amp;gt; 阻塞: 等待锁
    阻塞 --&amp;gt; 就绪: 获得锁
    运行 --&amp;gt; 等待: wait / join / await
    等待 --&amp;gt; 就绪: notify / 超时 / 被等待线程结束
    运行 --&amp;gt; 超时等待: sleep / wait(timeout)
    超时等待 --&amp;gt; 就绪: 时间到
    运行 --&amp;gt; 终止: 执行完毕&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #2&lt;/strong&gt;：&lt;code&gt;sleep&lt;/code&gt; 不释放锁，若在 synchronized 块内 sleep，其他线程会被长时间阻塞。需要“让出锁去等”时，用 &lt;code&gt;wait/Condition.await&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三多用-juc-同步类少用-waitnotify&#34;&gt;三、多用 JUC 同步类，少用 wait/notify&lt;/h2&gt;
&lt;h3 id=&#34;31-semaphore信号量&#34;&gt;3.1 Semaphore（信号量）&lt;/h3&gt;
&lt;p&gt;信号量维护一组“许可”，控制同时访问某资源的线程数量。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Semaphore semaphore &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Semaphore(3); &lt;span style=&#34;color:#75715e&#34;&gt;// 最多 3 个线程并发&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    semaphore.&lt;span style=&#34;color:#a6e22e&#34;&gt;acquire&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 访问受限资源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;finally&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    semaphore.&lt;span style=&#34;color:#a6e22e&#34;&gt;release&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[线程1] --&amp;gt;|acquire| S[许可池 3]
    B[线程2] --&amp;gt;|acquire| S
    C[线程3] --&amp;gt;|acquire| S
    D[线程4] --&amp;gt;|acquire 阻塞| S
    S --&amp;gt;|release| S&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #3&lt;/strong&gt;：&lt;code&gt;release()&lt;/code&gt; 一定要放在 &lt;code&gt;finally&lt;/code&gt; 里，否则异常会导致许可泄漏，最终所有线程都拿不到许可。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;32-countdownlatch-与-cyclicbarrier&#34;&gt;3.2 CountDownLatch 与 CyclicBarrier&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;特性&lt;/th&gt;
					&lt;th&gt;CountDownLatch&lt;/th&gt;
					&lt;th&gt;CyclicBarrier&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;方向&lt;/td&gt;
					&lt;td&gt;一个线程等待其他线程&lt;/td&gt;
					&lt;td&gt;多个线程互相等待&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;可复用&lt;/td&gt;
					&lt;td&gt;否（一次性）&lt;/td&gt;
					&lt;td&gt;是（可 reset）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;计数归零后&lt;/td&gt;
					&lt;td&gt;门闩打开，直接退出&lt;/td&gt;
					&lt;td&gt;所有线程同时继续&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    subgraph CountDownLatch
        M[主线程 await] -.-&amp;gt;|计数=0| M2[继续执行]
        W1[工作线程1] --&amp;gt;|countDown| C[计数器]
        W2[工作线程2] --&amp;gt;|countDown| C
    end

    subgraph CyclicBarrier
        T1[线程A await] --&amp;gt; B[屏障]
        T2[线程B await] --&amp;gt; B
        T3[线程C await] --&amp;gt; B
        B --&amp;gt;|全部到达| Go[一起继续]
    end&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #4&lt;/strong&gt;：不要把 &lt;code&gt;CountDownLatch&lt;/code&gt; 当循环栅栏用，计数到 0 后无法重置；需要循环同步用 &lt;code&gt;CyclicBarrier&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;33-exchanger&#34;&gt;3.3 Exchanger&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Exchanger&lt;/code&gt; 让两个线程在某个同步点交换数据，适合生产者-消费者配对场景，但使用频率较低。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四volatile可见性与有序性但不保证原子性&#34;&gt;四、volatile：可见性与有序性，但不保证原子性&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;volatile&lt;/code&gt; 的三条语义：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;可见性&lt;/strong&gt;：写操作会刷入主内存，读操作会从主内存刷新。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;有序性&lt;/strong&gt;：禁止指令重排序（happens-before）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不保证原子性&lt;/strong&gt;：复合操作（如 &lt;code&gt;i++&lt;/code&gt;）仍需要锁或原子类。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[线程A 写 volatile flag=true] --&amp;gt;| happens-before | B[线程B 读 flag]
    B --&amp;gt; C[线程B 看到 flag 之前所有写入]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 错误示例：volatile 不能保证 i++ 原子&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;volatile&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;increment&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    count&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;// 读-改-写，非原子&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 正确做法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; AtomicInteger count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; AtomicInteger(0);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;increment&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    count.&lt;span style=&#34;color:#a6e22e&#34;&gt;incrementAndGet&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #5&lt;/strong&gt;：只有在&lt;strong&gt;单次写、多次读、且不依赖前值&lt;/strong&gt;的场景下才用 &lt;code&gt;volatile&lt;/code&gt;（如状态标志 &lt;code&gt;volatile boolean running = true&lt;/code&gt;）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五死锁原因与破解&#34;&gt;五、死锁：原因与破解&lt;/h2&gt;
&lt;h3 id=&#34;51-典型死锁&#34;&gt;5.1 典型死锁&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    T1[线程1] --&amp;gt;|持有 A 锁| B[等待 B 锁]
    T2[线程2] --&amp;gt;|持有 B 锁| A[等待 A 锁]
    B --&amp;gt; T2
    A --&amp;gt; T1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 错误：锁顺序不一致&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;devoid &lt;span style=&#34;color:#a6e22e&#34;&gt;transfer&lt;/span&gt;(Account a, Account b, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; amount) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;synchronized&lt;/span&gt;(a) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;synchronized&lt;/span&gt;(b) { ... }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;52-常见诱因&#34;&gt;5.2 常见诱因&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;不一致的加锁顺序&lt;/strong&gt;：两个线程以不同顺序获取多把锁。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;在同步块内调用外部同步方法&lt;/strong&gt;：引入了不可控的锁依赖。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;持锁等待 I/O / 网络 / 用户输入&lt;/strong&gt;：放大了死锁窗口。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;53-破解方案&#34;&gt;5.3 破解方案&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;全局统一锁顺序&lt;/strong&gt;：先按对象哈希值排序再加锁。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 &lt;code&gt;tryLock&lt;/code&gt; 超时获取锁&lt;/strong&gt;，失败则回退并重试。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;减少锁粒度&lt;/strong&gt;，避免在同步块内调用外部方法（Open Call）。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 使用 ReentrantLock 的 tryLock 避免死锁&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (lockA.&lt;span style=&#34;color:#a6e22e&#34;&gt;tryLock&lt;/span&gt;(1, TimeUnit.&lt;span style=&#34;color:#a6e22e&#34;&gt;SECONDS&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (lockB.&lt;span style=&#34;color:#a6e22e&#34;&gt;tryLock&lt;/span&gt;(1, TimeUnit.&lt;span style=&#34;color:#a6e22e&#34;&gt;SECONDS&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#75715e&#34;&gt;// 执行业务&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#66d9ef&#34;&gt;finally&lt;/span&gt; { lockB.&lt;span style=&#34;color:#a6e22e&#34;&gt;unlock&lt;/span&gt;(); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;finally&lt;/span&gt; { lockA.&lt;span style=&#34;color:#a6e22e&#34;&gt;unlock&lt;/span&gt;(); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #6&lt;/strong&gt;：死锁往往不是锁本身的问题，而是&lt;strong&gt;锁的顺序和依赖关系&lt;/strong&gt;的问题。设计阶段先画锁依赖图，能发现大部分隐患。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六公平锁-vs-非公平锁&#34;&gt;六、公平锁 vs 非公平锁&lt;/h2&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ReentrantLock fairLock &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ReentrantLock(&lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;);   &lt;span style=&#34;color:#75715e&#34;&gt;// 公平&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ReentrantLock unfairLock &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ReentrantLock(&lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;); &lt;span style=&#34;color:#f92672&#34;&gt;//&lt;/span&gt; 非公平&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;（&lt;/span&gt;默认&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;）&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    subgraph 公平锁
        Q[等待队列 T1→T2→T3] --&amp;gt;|按顺序| L[锁]
    end
    subgraph 非公平锁
        N[新线程] --&amp;gt;|插队尝试| L2[锁]
        Q2[队列 T1→T2] -.-&amp;gt;|可能继续等待| L2
    end&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;公平锁&lt;/strong&gt;：按请求顺序分配锁，减少饥饿，但上下文切换多、吞吐低。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;非公平锁&lt;/strong&gt;：允许“插队”，若锁恰好可用，新线程可直接获取，减少唤醒延迟；但老线程可能长时间等待。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #7&lt;/strong&gt;：默认选&lt;strong&gt;非公平锁&lt;/strong&gt;即可，性能更好。除非业务明确要求严格的调度公平性（如资源分配器），否则不必打开公平模式。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七condition比-waitnotify-更精确的线程协作&#34;&gt;七、Condition：比 wait/notify 更精确的线程协作&lt;/h2&gt;
&lt;p&gt;一个 &lt;code&gt;ReentrantLock&lt;/code&gt; 可以创建多个 &lt;code&gt;Condition&lt;/code&gt;，分别管理不同的等待队列。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    L[ReentrantLock] --&amp;gt; C1[Condition A 队列]
    L --&amp;gt; C2[Condition B 队列]
    L --&amp;gt; C3[Condition C 队列]
    C1 --&amp;gt;|signal| W1[唤醒指定线程]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;PrintABC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Lock lock &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ReentrantLock();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Condition a &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; lock.&lt;span style=&#34;color:#a6e22e&#34;&gt;newCondition&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Condition b &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; lock.&lt;span style=&#34;color:#a6e22e&#34;&gt;newCondition&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Condition c &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; lock.&lt;span style=&#34;color:#a6e22e&#34;&gt;newCondition&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;volatile&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; index &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(String name, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; expect, Condition wait, Condition next) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Thread(() &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            lock.&lt;span style=&#34;color:#a6e22e&#34;&gt;lock&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (index &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; expect) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    wait.&lt;span style=&#34;color:#a6e22e&#34;&gt;await&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                System.&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                index &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (expect &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; 1) &lt;span style=&#34;color:#f92672&#34;&gt;%&lt;/span&gt; 3;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                next.&lt;span style=&#34;color:#a6e22e&#34;&gt;signal&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; (InterruptedException e) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Thread.&lt;span style=&#34;color:#a6e22e&#34;&gt;currentThread&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;interrupt&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#66d9ef&#34;&gt;finally&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                lock.&lt;span style=&#34;color:#a6e22e&#34;&gt;unlock&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }).&lt;span style=&#34;color:#a6e22e&#34;&gt;start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PrintABC p &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; PrintABC();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        p.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;, 0, p.&lt;span style=&#34;color:#a6e22e&#34;&gt;a&lt;/span&gt;, p.&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        p.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;B&amp;#34;&lt;/span&gt;, 1, p.&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;, p.&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        p.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;C&amp;#34;&lt;/span&gt;, 2, p.&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;, p.&lt;span style=&#34;color:#a6e22e&#34;&gt;a&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #8&lt;/strong&gt;：&lt;code&gt;Condition.await/signal&lt;/code&gt; 与 &lt;code&gt;wait/notify&lt;/code&gt; 一样，必须在持有锁的线程中调用，且 &lt;code&gt;await&lt;/code&gt; 要用 &lt;code&gt;while&lt;/code&gt; 循环而不是 &lt;code&gt;if&lt;/code&gt;，防止虚假唤醒。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八线程池不要裸开线程&#34;&gt;八、线程池：不要裸开线程&lt;/h2&gt;
&lt;h3 id=&#34;81-常见工厂方法&#34;&gt;8.1 常见工厂方法&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;方法&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
					&lt;th&gt;隐患&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;newSingleThreadExecutor&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;单线程，按提交顺序执行&lt;/td&gt;
					&lt;td&gt;无界队列，任务堆积会 OOM&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;newFixedThreadPool(n)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;固定线程数&lt;/td&gt;
					&lt;td&gt;同样使用无界队列&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;newCachedThreadPool&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;线程可复用、可无限创建&lt;/td&gt;
					&lt;td&gt;高并发下线程数爆炸&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;newScheduledThreadPool&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;支持定时/周期任务&lt;/td&gt;
					&lt;td&gt;注意任务异常终止&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;82-threadpoolexecutor-核心参数&#34;&gt;8.2 ThreadPoolExecutor 核心参数&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    T[提交任务] --&amp;gt;|核心线程数未满| C[创建核心线程]
    T --&amp;gt;|队列未满| Q[进入阻塞队列]
    T --&amp;gt;|队列满且线程数&amp;lt;max| M[创建非核心线程]
    T --&amp;gt;|队列满且线程数=max| R[拒绝策略]
    C --&amp;gt; E[执行]
    Q --&amp;gt; E
    M --&amp;gt; E&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ThreadPoolExecutor executor &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ThreadPoolExecutor(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    4,                      &lt;span style=&#34;color:#75715e&#34;&gt;// 核心线程数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    8,                      &lt;span style=&#34;color:#75715e&#34;&gt;// 最大线程数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    60L, TimeUnit.&lt;span style=&#34;color:#a6e22e&#34;&gt;SECONDS&lt;/span&gt;,  &lt;span style=&#34;color:#75715e&#34;&gt;// 非核心线程空闲存活时间&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ArrayBlockingQueue&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;gt;&lt;/span&gt;(100), &lt;span style=&#34;color:#75715e&#34;&gt;// 有界队列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ThreadFactoryBuilder().&lt;span style=&#34;color:#a6e22e&#34;&gt;setNameFormat&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;biz-pool-%d&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ThreadPoolExecutor.&lt;span style=&#34;color:#a6e22e&#34;&gt;CallerRunsPolicy&lt;/span&gt;() &lt;span style=&#34;color:#75715e&#34;&gt;// 拒绝策略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #9&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;生产环境尽量直接创建 &lt;code&gt;ThreadPoolExecutor&lt;/code&gt;，不要用 Executors 的便捷工厂（无界队列/无限线程是 OOM 元凶）。&lt;/li&gt;
&lt;li&gt;任务抛异常会导致线程被回收重建，建议任务内部 &lt;code&gt;try/catch&lt;/code&gt; 并记录。&lt;/li&gt;
&lt;li&gt;应用关闭前调用 &lt;code&gt;shutdown()&lt;/code&gt; 或 &lt;code&gt;shutdownNow()&lt;/code&gt;，否则 JVM 可能不会退出。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九阻塞队列&#34;&gt;九、阻塞队列&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;队列&lt;/th&gt;
					&lt;th&gt;有界性&lt;/th&gt;
					&lt;th&gt;实现&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ArrayBlockingQueue&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;有界&lt;/td&gt;
					&lt;td&gt;数组 + ReentrantLock&lt;/td&gt;
					&lt;td&gt;高吞吐、需要指定容量&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;LinkedBlockingQueue&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;可选有界&lt;/td&gt;
					&lt;td&gt;链表 + 两把锁（take/put）&lt;/td&gt;
					&lt;td&gt;默认无界，小心 OOM&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;PriorityBlockingQueue&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;无界&lt;/td&gt;
					&lt;td&gt;堆&lt;/td&gt;
					&lt;td&gt;按优先级出队&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DelayQueue&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;无界&lt;/td&gt;
					&lt;td&gt;堆&lt;/td&gt;
					&lt;td&gt;元素到延迟时间才能出队&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SynchronousQueue&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;零容量&lt;/td&gt;
					&lt;td&gt;无缓冲区&lt;/td&gt;
					&lt;td&gt;一手交钱一手交货&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;LinkedTransferQueue&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;无界&lt;/td&gt;
					&lt;td&gt;无锁 CAS&lt;/td&gt;
					&lt;td&gt;支持 transfer 直接传递&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;LinkedBlockingDeque&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;无界&lt;/td&gt;
					&lt;td&gt;双向链表&lt;/td&gt;
					&lt;td&gt;支持两端操作&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    P[生产者 put] --&amp;gt; Q[阻塞队列]
    Q --&amp;gt; C[消费者 take]
    P -.-&amp;gt;|队列满| W1[阻塞]
    C -.-&amp;gt;|队列空| W2[阻塞]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #10&lt;/strong&gt;：无界阻塞队列在生产者快、消费者慢时会把内存撑爆。优先使用 &lt;code&gt;ArrayBlockingQueue&lt;/code&gt; 或指定容量的 &lt;code&gt;LinkedBlockingQueue&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十自旋锁reentrantlock-与-synchronized&#34;&gt;十、自旋锁、ReentrantLock 与 synchronized&lt;/h2&gt;
&lt;h3 id=&#34;101-自旋锁&#34;&gt;10.1 自旋锁&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SpinLock&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; AtomicReference&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Thread&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; owner &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; AtomicReference&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;gt;&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;lock&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Thread t &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Thread.&lt;span style=&#34;color:#a6e22e&#34;&gt;currentThread&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;owner.&lt;span style=&#34;color:#a6e22e&#34;&gt;compareAndSet&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;, t)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// 自旋等待，不进入内核态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;unlock&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Thread t &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Thread.&lt;span style=&#34;color:#a6e22e&#34;&gt;currentThread&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        owner.&lt;span style=&#34;color:#a6e22e&#34;&gt;compareAndSet&lt;/span&gt;(t, &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[互斥锁 sleep] --&amp;gt;|上下文切换| B[内核阻塞]
    C[自旋锁 CAS] --&amp;gt;|用户态循环| D[CPU 忙等]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;优点：没有线程上下文切换开销。&lt;/li&gt;
&lt;li&gt;缺点：持锁时间长会浪费 CPU；&lt;strong&gt;同一线程不可重入&lt;/strong&gt;，递归调用会死锁。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;102-reentrantlock-与-synchronized-对比&#34;&gt;10.2 ReentrantLock 与 synchronized 对比&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;能力&lt;/th&gt;
					&lt;th&gt;synchronized&lt;/th&gt;
					&lt;th&gt;ReentrantLock&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;可重入&lt;/td&gt;
					&lt;td&gt;是&lt;/td&gt;
					&lt;td&gt;是&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;可中断&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;lockInterruptibly()&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;超时获取&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;tryLock(timeout)&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;公平锁&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;可选&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;多条件队列&lt;/td&gt;
					&lt;td&gt;一个 wait set&lt;/td&gt;
					&lt;td&gt;多个 Condition&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;性能&lt;/td&gt;
					&lt;td&gt;JDK6+ 优化后接近&lt;/td&gt;
					&lt;td&gt;接近&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #11&lt;/strong&gt;：&lt;code&gt;ReentrantLock&lt;/code&gt; 必须显式 &lt;code&gt;unlock()&lt;/code&gt;，否则即使异常也会死锁；务必放在 &lt;code&gt;finally&lt;/code&gt; 中。&lt;code&gt;synchronized&lt;/code&gt; 则由 JVM 保证自动释放。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;103-偏向锁&#34;&gt;10.3 偏向锁&lt;/h3&gt;
&lt;p&gt;偏向锁是 JVM 对&lt;strong&gt;无竞争同步&lt;/strong&gt;的优化：第一次获取锁时把线程 ID 记录到对象头，之后同一线程再进入无需 CAS。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：JDK 15 开始偏向锁默认禁用（&lt;code&gt;-XX:+UseBiasedLocking&lt;/code&gt; 已废弃），因为现代应用中锁竞争更频繁，撤销偏向锁的开销反而可能大于收益。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十一线程安全的-singleton&#34;&gt;十一、线程安全的 Singleton&lt;/h2&gt;
&lt;h3 id=&#34;111-饿汉式类加载时初始化&#34;&gt;11.1 饿汉式（类加载时初始化）&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Singleton&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Singleton INSTANCE &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Singleton();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Singleton&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Singleton &lt;span style=&#34;color:#a6e22e&#34;&gt;getInstance&lt;/span&gt;() { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; INSTANCE; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;借助类加载机制保证线程安全，简单可靠；若实例创建开销大且未必使用，则浪费资源。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;112-静态内部类推荐&#34;&gt;11.2 静态内部类（推荐）&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Singleton&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Singleton&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Holder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Singleton INSTANCE &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Singleton();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Singleton &lt;span style=&#34;color:#a6e22e&#34;&gt;getInstance&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Holder.&lt;span style=&#34;color:#a6e22e&#34;&gt;INSTANCE&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[调用 getInstance] --&amp;gt;|首次触发| B[加载 Holder 类]
    B --&amp;gt; C[初始化 INSTANCE]
    C --&amp;gt; D[返回唯一实例]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;延迟加载 + 类加载保证线程安全，是大多数场景下的最佳实践。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;113-双重检查锁dcl-volatile&#34;&gt;11.3 双重检查锁（DCL）+ volatile&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Singleton&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Singleton&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;volatile&lt;/span&gt; Singleton instance;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Singleton &lt;span style=&#34;color:#a6e22e&#34;&gt;getInstance&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (instance &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;synchronized&lt;/span&gt; (Singleton.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (instance &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    instance &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Singleton(); &lt;span style=&#34;color:#75715e&#34;&gt;// 禁止指令重排&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; instance;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #12&lt;/strong&gt;：DCL 必须加 &lt;code&gt;volatile&lt;/code&gt;，否则 &lt;code&gt;new Singleton()&lt;/code&gt; 的指令重排会导致其他线程读到未构造完成的对象。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十二synchronized-的底层行为&#34;&gt;十二、synchronized 的底层行为&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;synchronized&lt;/code&gt; 可以修饰方法或代码块，锁对象分别是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;实例方法：当前实例 &lt;code&gt;this&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;静态方法：类的 &lt;code&gt;Class&lt;/code&gt; 对象。&lt;/li&gt;
&lt;li&gt;代码块：括号里指定的对象。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    O[对象头 Mark Word] --&amp;gt;|无锁| A[无锁状态]
    A --&amp;gt;|第一个线程获取| B[偏向锁]
    B --&amp;gt;|出现竞争| C[轻量级锁 CAS]
    C --&amp;gt;|竞争加剧| D[重量级锁 操作系统 Mutex]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #13&lt;/strong&gt;：不要把 &lt;code&gt;synchronized&lt;/code&gt; 当成“只要包住就安全”的万金油。锁的对象要选对，锁的粒度要尽量小，避免锁住整个方法或无关代码。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十三避坑速查表&#34;&gt;十三、避坑速查表&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;不要这样做&lt;/th&gt;
					&lt;th&gt;推荐做法&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;手写 &lt;code&gt;wait/notify&lt;/code&gt; 做复杂协调&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;CountDownLatch&lt;/code&gt;、&lt;code&gt;CyclicBarrier&lt;/code&gt;、&lt;code&gt;Semaphore&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;用 &lt;code&gt;volatile&lt;/code&gt; 做 &lt;code&gt;i++&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;AtomicInteger&lt;/code&gt; 或 &lt;code&gt;LongAdder&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;裸 &lt;code&gt;new Thread()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;ThreadPoolExecutor&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Executors.newFixedThreadPool&lt;/code&gt; 无脑用&lt;/td&gt;
					&lt;td&gt;自定义有界队列 + 拒绝策略&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;在锁里调外部同步方法 / 阻塞 I/O&lt;/td&gt;
					&lt;td&gt;缩小锁范围，使用 Open Call&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;不一致的加锁顺序&lt;/td&gt;
					&lt;td&gt;全局排序或使用 &lt;code&gt;tryLock&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;DCL 不加 &lt;code&gt;volatile&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;必须加 &lt;code&gt;volatile&lt;/code&gt;，或改用静态内部类&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;自旋锁里递归加锁&lt;/td&gt;
					&lt;td&gt;使用可重入锁 &lt;code&gt;ReentrantLock&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;忽略 &lt;code&gt;InterruptedException&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;恢复中断标志 &lt;code&gt;Thread.currentThread().interrupt()&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;线程池任务吞掉异常&lt;/td&gt;
					&lt;td&gt;任务内部 &lt;code&gt;try/catch&lt;/code&gt; 或使用 &lt;code&gt;Future.get()&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十四总结&#34;&gt;十四、总结&lt;/h2&gt;
&lt;p&gt;Java 高并发编程的演进路径，其实是从“手动管理线程和锁”走向“使用高层抽象”。牢记下面三句话：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;能不变就不变&lt;/strong&gt;：优先使用不可变对象、线程封闭和 JUC 并发集合。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;能用高层就不用底层&lt;/strong&gt;：用 &lt;code&gt;Semaphore&lt;/code&gt;、&lt;code&gt;CountDownLatch&lt;/code&gt;、&lt;code&gt;Executor&lt;/code&gt; 替代 &lt;code&gt;wait/notify&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;锁是最后手段&lt;/strong&gt;：如果必须用锁，确保加锁顺序一致、粒度最小、持有时间最短。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;把这三点落地到代码里，配合上面的图例和示例，就能避开大多数并发陷阱。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;参考与延伸阅读&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;《Java 并发编程实战》（Java Concurrency in Practice）&lt;/li&gt;
&lt;li&gt;《Java 并发编程的艺术》&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/package-summary.html&#34;&gt;JDK 文档：java.util.concurrent&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
