深度分析Java多線程機制

Java 多線程是掌握高性能、高響應性應用程序開發的關鍵,它涉及到語言特性、JVM 實現、操作系統交互以及并發編程的核心概念。

核心目標: 充分利用現代多核 CPU 的計算能力,提高程序吞吐量(單位時間內處理的任務量)和響應性(避免用戶界面卡死)。

一、 核心概念與基礎

  1. 進程 vs. 線程:

    • 進程: 操作系統分配資源(內存、文件句柄、CPU 時間片)的基本單位。一個進程擁有獨立的地址空間,進程間通信(IPC)成本較高(如管道、套接字)。
    • 線程: 輕量級進程 (Lightweight Process, LWP)。是進程內的一個獨立執行流,共享其所屬進程的內存空間(堆、方法區)和資源(文件句柄等),但擁有獨立的程序計數器、虛擬機棧、本地方法棧和線程狀態。線程間通信和數據共享成本遠低于進程。一個 Java 程序(一個 JVM 進程)至少有一個主線程(main 方法所在線程)。
  2. Java 線程模型:

    • 1:1 模型 (內核級線程): 這是 Java 在主流操作系統(Windows, Linux, macOS)上默認采用的模型。每個 Java 線程直接映射到一個操作系統內核線程 (Kernel Thread)。由操作系統內核負責線程的調度和管理(CPU 時間片分配、上下文切換)。
      • 優點: 能真正利用多核 CPU 并行執行;阻塞操作(如 I/O)時,內核可以調度其他線程運行。
      • 缺點: 線程創建、銷毀、上下文切換涉及系統調用,開銷相對較大;受操作系統線程數限制。
    • 用戶級線程 (歷史/特定實現): 早期 Java 版本在某些平臺上可能使用過用戶級線程庫(如 Green Threads)。線程管理完全在用戶空間(JVM)進行,不依賴操作系統內核。創建/切換開銷小,但一個線程阻塞會導致整個進程阻塞,且無法利用多核。現代 Java 已不再使用純用戶級線程模型。
    • M:N 模型 (混合線程 - Java 虛擬線程): Java 19 (Preview) / Java 21 (正式) 引入的 虛擬線程 (Virtual Threads) 采用此模型。多個虛擬線程 (M) 映射到少量操作系統線程 (N) 上執行。由 JVM 負責調度虛擬線程,在遇到阻塞操作時,JVM 能自動將虛擬線程掛起,并將底層承載線程 (Carrier Thread) 釋放出來執行其他虛擬線程,避免阻塞 OS 線程。
      • 優點: 極大降低創建和管理高并發(成千上萬)線程的開銷;簡化高吞吐量并發代碼(特別是 I/O 密集型)。
      • 關系: 虛擬線程建立在強大的 java.util.concurrent 基礎之上,是對傳統平臺線程 (java.lang.Thread) 的補充,而非替代。兩者可以共存。
  3. 線程生命周期 (狀態):
    Java 線程在其生命周期中會處于以下狀態之一(定義在 Thread.State 枚舉中):

    • NEW 線程對象已創建 (new Thread()),但尚未調用 start() 方法。
    • RUNNABLE 調用 start() 后進入此狀態。注意: 這表示線程可以運行,但不一定正在 CPU 上執行。它可能在等待操作系統分配 CPU 時間片。包含了操作系統層面的 ReadyRunning 狀態。
    • BLOCKED 線程試圖獲取一個由其他線程持有的對象監視器鎖 (synchronized) 而進入阻塞狀態。只有獲得鎖才能退出此狀態
    • WAITING 線程等待另一個線程執行特定操作(通知或中斷),無限期等待。進入方式:
      • Object.wait() (不指定超時)
      • Thread.join() (不指定超時)
      • LockSupport.park()
    • TIMED_WAITING 線程在指定時間段內等待另一個線程執行特定操作。進入方式:
      • Thread.sleep(long millis)
      • Object.wait(long timeout)
      • Thread.join(long millis)
      • LockSupport.parkNanos(long nanos) / LockSupport.parkUntil(long deadline)
    • TERMINATED 線程執行完 run() 方法或因異常退出。

二、 創建與啟動線程

  1. 繼承 Thread 類:

    class MyThread extends Thread {@Overridepublic void run() {// 線程要執行的代碼}
    }
    MyThread thread = new MyThread();
    thread.start(); // 關鍵!調用 start() 讓 JVM 安排執行 run(),不是直接調用 run()!
    
  2. 實現 Runnable 接口 (推薦):

    class MyRunnable implements Runnable {@Overridepublic void run() {// 線程要執行的代碼}
    }
    Thread thread = new Thread(new MyRunnable());
    thread.start();
    // 或使用 Lambda 表達式簡化
    Thread lambdaThread = new Thread(() -> {// 線程要執行的代碼
    });
    lambdaThread.start();
    
    • 優勢: 避免了單繼承的限制;更符合面向對象設計(任務與執行者分離);便于線程池使用。
  3. 實現 Callable 接口 (帶返回值):

    class MyCallable implements Callable {@Overridepublic String call() throws Exception {// 線程要執行的代碼,可返回結果,可拋出異常return "Result";}
    }
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Future future = executor.submit(new MyCallable());
    String result = future.get(); // 阻塞獲取結果
    executor.shutdown();
    
    • 通常與 ExecutorService (線程池) 結合使用,通過 Future 獲取異步計算結果。
  4. 虛擬線程 (Java 19+):

    // Java 21+
    Thread virtualThread = Thread.ofVirtual().start(() -> {// 線程要執行的代碼 (I/O 密集型很合適)
    });
    // 或使用 Executors.newVirtualThreadPerTaskExecutor()
    
    • 創建開銷極小,適合大量并發任務(特別是涉及阻塞 I/O 的)。

關鍵點: 必須調用 start() 方法來啟動新線程。直接調用 run() 方法只是在當前線程中執行該方法,并沒有創建新的執行流。

三、 線程同步與通信 - 核心挑戰

多個線程共享進程內存空間,對共享數據的并發訪問可能導致競態條件 (Race Condition)數據不一致同步 (Synchronization) 是協調線程對共享資源訪問的機制,確保線程安全 (Thread Safety)。

  1. 內置鎖 (監視器鎖) - synchronized 關鍵字:

    • 機制: 基于對象的內置鎖 (Intrinsic Lock / Monitor Lock)。每個 Java 對象都有一個與之關聯的鎖。
    • 用法:
      • 同步代碼塊: synchronized (lockObject) { ... } - 顯式指定鎖對象。
      • 同步實例方法: public synchronized void method() { ... } - 鎖是調用該方法的當前對象實例 (this)
      • 同步靜態方法: public static synchronized void method() { ... } - 鎖是該方法所屬的 Class 對象
    • 原理:
      • 線程進入 synchronized 塊/方法前,必須獲得指定對象的鎖。
      • 如果鎖已被其他線程持有,當前線程進入 BLOCKED 狀態等待。
      • 線程執行完 synchronized 塊/方法后,會自動釋放鎖。
      • 鎖是可重入 (Reentrant) 的:持有鎖的線程可以再次獲取同一個鎖(避免自身死鎖)。
    • 特點: 簡單易用,JVM 內置支持。但粒度較粗(方法或代碼塊),容易導致死鎖、性能下降(鎖競爭)。
  2. volatile 關鍵字:

    • 目標: 解決內存可見性問題,不保證原子性
    • 可見性: 對一個 volatile 變量的寫操作,會立即刷新到主內存。對一個 volatile 變量的讀操作,會從主內存中讀取最新值(繞過線程工作內存/緩存)。
    • 禁止指令重排序: JVM 和 CPU 會對指令進行優化重排序以提高性能。volatile 讀寫操作會插入內存屏障 (Memory Barrier),限制其前后指令的重排序,保證一定的順序性。
    • 適用場景: 狀態標志位(如 volatile boolean running;),double-checked locking 的單例模式實現(需要結合 synchronized)。
  3. java.util.concurrent 包 (JUC):
    提供了更強大、更靈活的并發工具,是構建高性能并發應用的首選。核心組件:

    • 鎖 (Lock):
      • Lock 接口 (如 ReentrantLock): 提供比 synchronized 更靈活的鎖操作(可中斷、超時、嘗試獲取、公平鎖/非公平鎖選擇)。
      • ReadWriteLock 接口 (如 ReentrantReadWriteLock): 允許多個讀線程并發訪問,但寫線程獨占訪問(提高讀多寫少場景性能)。
    • 原子變量 (Atomic Variables):
      • AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference 等。
      • 利用 CAS (Compare-And-Swap) 硬件指令(通過 sun.misc.Unsafe 或 JVM 內在函數)實現無鎖(Lock-Free)的原子操作(如 incrementAndGet(), compareAndSet())。
      • 性能通常優于鎖(在低到中度競爭下),避免上下文切換開銷。
      • 是構建高性能非阻塞算法的基礎。
    • 并發容器 (Concurrent Collections):
      • ConcurrentHashMap: 高并發、線程安全的 HashMap 實現(分段鎖或 CAS)。
      • CopyOnWriteArrayList/CopyOnWriteArraySet: 寫時復制,適合讀多寫少場景。
      • ConcurrentLinkedQueue/ConcurrentLinkedDeque: 無界、非阻塞、線程安全的隊列(基于 CAS)。
      • BlockingQueue 接口及其實現 (ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue, DelayQueue): 提供阻塞的 put()/take() 操作,是生產者-消費者模型的基石。
    • 線程池 (Thread Pools - ExecutorService):
      • 核心思想: 預先創建一組線程并管理其生命周期,通過任務隊列接受并執行提交的任務 (Runnable/Callable)。
      • 優勢:
        • 降低線程創建/銷毀的開銷。
        • 控制并發線程數量,避免資源耗盡。
        • 提供任務隊列和多種拒絕策略。
        • 方便管理和監控。
      • 關鍵組件:
        • Executor / ExecutorService / ScheduledExecutorService 接口。
        • ThreadPoolExecutor: 最靈活、可配置的核心線程池實現。
        • Executors 工廠類:提供創建常用配置線程池的便捷方法(但需注意潛在問題,如 newFixedThreadPool 的無界隊列可能導致 OOM)。
      • 重要配置參數: 核心線程數、最大線程數、任務隊列、線程工廠、拒絕策略 (AbortPolicy, CallerRunsPolicy, DiscardPolicy, DiscardOldestPolicy)。
    • 同步工具 (Synchronizers):
      • CountDownLatch: 等待一組操作完成。初始化一個計數器,線程調用 countDown() 減 1,調用 await() 的線程阻塞直到計數器為 0。
      • CyclicBarrier: 讓一組線程在某個公共屏障點等待,直到所有線程都到達屏障后才一起繼續執行。可重用。
      • Semaphore: 控制訪問特定資源的線程數量(許可證)。acquire() 獲取許可,release() 釋放許可。
      • Exchanger: 兩個線程在同步點交換數據。
      • Phaser (Java 7+): 更靈活、可重用的同步屏障,支持動態注冊/注銷參與線程,分階段同步。
    • Future 與 CompletableFuture:
      • Future: 表示異步計算的結果。提供檢查是否完成、等待完成、獲取結果的方法(阻塞)。
      • CompletableFuture (Java 8+): 強大的異步編程工具。支持顯式完成、鏈式調用(thenApply, thenAccept, thenRun, thenCompose)、組合多個異步任務(thenCombine, allOf, anyOf)、異常處理(exceptionally, handle)。極大地簡化了異步、非阻塞代碼的編寫。

四、 Java 內存模型 (JMM)

JMM 定義了線程如何以及何時可以看到其他線程寫入共享變量的值,以及在必要時如何同步訪問共享變量。它是理解 synchronized, volatile, finalhappens-before 關系的基礎。

  1. 抽象模型:

    • 每個線程有自己的工作內存 (Working Memory)(可視為 CPU 寄存器、緩存等的抽象)。
    • 所有線程共享主內存 (Main Memory)(堆內存)。
    • 線程對變量的所有操作(讀/寫)都必須在工作內存中進行,不能直接讀寫主內存。
    • 線程間變量值的傳遞需要通過主內存來完成。
  2. 內存間交互操作:
    JMM 定義了 8 種原子操作(lock, unlock, read, load, use, assign, store, write)以及它們之間的順序規則,但開發者主要關注其提供的可見性保證

  3. happens-before 原則:
    JMM 的核心是 happens-before 關系。它定義了兩個操作之間的可見性保證:如果一個操作 A happens-before 操作 B,那么 A 所做的任何修改(寫操作)對 B 都是可見的。

    • 程序順序規則: 同一個線程中的每個操作,happens-before 于該線程中任意的后續操作。
    • 監視器鎖規則: 對一個鎖的解鎖 (unlock),happens-before 于后續對這個鎖的加鎖 (lock)。
    • volatile 變量規則: 對一個 volatile 變量的寫,happens-before 于任意后續對這個 volatile 變量的讀。
    • 線程啟動規則: Thread.start() 調用 happens-before 于被啟動線程中的任何操作。
    • 線程終止規則: 線程中的所有操作 happens-before 于其他線程檢測到該線程已經終止(通過 Thread.join() 返回或 Thread.isAlive() 返回 false)。
    • 中斷規則: 一個線程調用另一個線程的 interrupt() happens-before 于被中斷線程檢測到中斷(拋出 InterruptedException 或調用 isInterrupted()/interrupted())。
    • 傳遞性: 如果 A happens-before B,且 B happens-before C,那么 A happens-before C
  4. final 字段的特殊性:
    在對象構造器結束時,final 字段的值保證對其他線程可見(無需同步),前提是構造器沒有將 this 引用逸出 (this escape)。

JMM 的意義: 它告訴開發者,在缺乏適當的同步(synchronized, volatile, JUC 工具)的情況下,一個線程對共享變量的修改,另一個線程不一定能立即、甚至永遠看不到happens-before 規則是 JVM 必須遵守的契約,也是開發者編寫正確并發程序的依據。

五、 高級主題與最佳實踐

  1. 死鎖 (Deadlock) 與活鎖 (Livelock):

    • 死鎖: 兩個或多個線程互相持有對方需要的鎖而無限期等待。必要條件:互斥、請求與保持、不可剝奪、循環等待。
    • 預防/避免: 固定加鎖順序、使用超時鎖 (tryLock(timeout))、死鎖檢測算法。
    • 活鎖: 線程持續響應對方動作(如反復重試)而無法取得進展。需要引入隨機性或退避策略。
  2. 線程中斷:

    • thread.interrupt():設置目標線程的中斷標志位(非強制終止)。
    • thread.isInterrupted():檢查線程是否被中斷(不清除標志)。
    • Thread.interrupted():檢查當前線程是否被中斷,并清除中斷標志。
    • 阻塞方法(如 sleep(), wait(), join())在阻塞時收到中斷信號會拋出 InterruptedException(拋出前會清除中斷標志)。正確處理中斷是編寫健壯多線程代碼的關鍵(通常選擇傳遞 InterruptedException 或恢復中斷狀態)。
  3. ThreadLocal

    • 為每個線程創建變量的獨立副本,解決共享變量沖突問題。
    • 常用于存儲線程上下文信息(如用戶會話 ID、數據庫連接),避免在方法間傳遞參數。
    • 注意內存泄漏: ThreadLocal 變量通常作為 static final 字段聲明。線程池中的線程可能長期存活,如果 ThreadLocal 值引用了大對象且不再使用,需要手動調用 remove() 清除,否則該對象無法被 GC。
  4. 性能考量與調優:

    • 減少鎖競爭: 縮小同步范圍、使用讀寫鎖、使用并發容器、使用原子變量、考慮無鎖數據結構。
    • 合理使用線程池: 根據任務類型(CPU 密集型 vs I/O 密集型)設置核心/最大線程數、選擇合適隊列和拒絕策略。避免使用無界隊列(可能導致 OOM)和 Executors.newCachedThreadPool()(可能導致創建過多線程),推薦手動創建 ThreadPoolExecutor
    • 利用虛擬線程 (Java 21+): 對于高并發、大量阻塞操作(尤其是 I/O)的任務,虛擬線程能顯著提升吞吐量和資源利用率。
    • 監控: 使用 JConsole, VisualVM, Java Mission Control 等工具監控線程狀態、死鎖、CPU 使用率。
  5. 結構化并發 (Java 21+ - Preview):

    • 旨在簡化并發任務的生命周期管理,特別是處理任務組及其子任務。
    • 核心思想:子任務的生命周期應限定在其父任務的語法塊內。使用 StructuredTaskScope
    • 優勢:提高代碼可讀性、可靠性和可維護性;自動處理取消和錯誤傳播;避免線程泄漏。

總結

Java 多線程機制是一個龐大而復雜的主題,其核心在于利用硬件并行能力安全高效地協調并發訪問共享資源。深入理解需要掌握:

  1. 線程模型與生命周期: 理解線程如何創建、執行、阻塞和終止。
  2. 同步原語: 從基礎的 synchronizedvolatile 到強大的 JUC 工具(鎖、原子類、并發容器、線程池、同步器),理解它們的原理、適用場景和優缺點。
  3. Java 內存模型 (JMM) 與 happens-before 這是理解內存可見性、指令重排序和編寫正確并發程序的理論基石。
  4. 高級問題處理: 死鎖/活鎖的識別與避免、正確的中斷處理、ThreadLocal 的合理使用與風險。
  5. 現代趨勢: 虛擬線程 (Virtual Threads) 極大地簡化了高吞吐量 I/O 密集型并發編程;結構化并發 (Structured Concurrency) 提升了并發代碼的可管理性和可靠性。

最佳實踐的核心永遠是:優先使用高級并發工具 (JUC),清晰理解共享狀態,最小化同步范圍,合理利用線程池,并時刻關注線程安全和性能。 隨著 Java 的演進(特別是虛擬線程和結構化并發),編寫高效、可維護的并發代碼將變得更加容易和安全。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92643.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92643.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92643.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android熱修復實現方案深度分析

熱修復的核心目標是在**不發布新版本、不重新安裝、不重啟應用(或僅輕量級重啟)**的情況下,修復線上應用的 Bug 或進行小范圍的功能更新,極大地提升用戶體驗和問題響應速度。 一、熱修復的核心原理 無論哪種方案,其核心…

HTML前端顏色漸變動畫完整指南

漸變動畫已經成為現代網頁設計中不可或缺的元素,它們不僅能為網站增添視覺吸引力,還能顯著提升用戶體驗。通過巧妙運用CSS漸變動畫,開發者可以創造出令人印象深刻的動態背景效果,而無需依賴圖片或復雜的腳本。 漸變動畫的魅力所在…

b-up:Enzo_mi:Transformer DETR系列

1.視頻1:self-Attention|自注意力機制 |位置編碼 | 理論 代碼 注意: q-查詢; k-商品標簽; v-值(具體商品) * 不是指乘法,類似概念 a1:相似度; b1:總分 若想…

算法題(179):單調棧

審題: 本題是單調棧的模板題 補充:單調棧 單調棧中的數據始終保持單調遞增或單調遞減 使用情景:給定一個數組,要求尋找 1.某個數左側,離他最近且值大于他的數 2.某個數左側,離他最近且值小于他的數 3.某個數…

CF每日5題(1500-1600)

545C 貪心 1500 題意:給 n 棵樹在一維數軸上的坐標 xix_ixi? ,以及它們的長度 hih_ihi?。現在要你砍倒這些樹,樹可以向左倒也可以向右倒,砍倒的樹不能重合、當然也不能覆蓋其他的樹原來的位置,現在求最大可以砍倒的…

HW藍隊:天眼告警監測分析之Web攻擊

Web攻擊 信息泄露 敏感數據包括但不限于:口令、密鑰、證書、會話標識、License、隱私數據(如短消息的內容)、授權憑據、個人數據(如姓名、住址、電話等)等,在程序文件、配置文件、日志文件、備份文件及數據庫中都有可能包含敏感數據 信息收集方法 漏洞分類 備份文…

大騰智能國產3D CAD軟件正式上架華為云云商店

深圳市大騰信息技術有限公司(以下簡稱“大騰智能”)與華為云達成深度合作,大騰智能CAD軟件及配套服務通過了華為云在功能適配、安全可用、穩定高效等方面的嚴選商品認證,已正式上架華為云云商店,成為華為云云商店的聯營…

論文復現-windows電腦在pycharm中運行.sh文件

1.更改終端路徑(前提:已下載git bash)2.授權打開pycharm終端,輸入 chmod x 文件名3.根據當前位置,運行.sh文件

開關電源安全保護電路:浪涌保護、過流保護、過壓保護

開關電源安全保護電路:浪涌保護、過流保護、過壓保護 引言 對于開關電源而言, 安全、可靠性歷來被視為重要的性能之一. 開關電源在電氣技術指標滿足電子設備正常使用要求的條件下, 還要滿足外界或自身電路或負載電路出現故障的情況下也能安全可靠地工作. 為此, 須有多種保護措…

C語言(十)

一、函數概述函數是面向過程編程思想的具體體現,主要作用:降低程序之間的耦合性提高代碼的復用性和可維護性一個完整的 C 程序由**一個或多個程序模塊(源文件)**組成。為便于開發與調試,通常會將代碼拆分為多個源文件&…

QT項目-仿QQ音樂的音樂播放器(第二節)

目錄 自定義控件: BtForm類中實現 BtForm上的動畫效果 自定義控件: 該控件實際由:圖?、?字、動畫三部分組成。圖?和?字分別?QLabel展?,動畫部分內部實際為4 個QLabel。 ① 將BtForm的geometry的寬度和?度修改為200*35。…

【世紀龍科技】數字課程資源-新能源汽車概論

一、課程介紹本課程為通過項目任務式教學,全面系統的講解了新能源汽車的基礎知識及相關技能,培養和提高學生的動手能力和理論知識的工程應用能力。以典型工作任務帶動知識與技能的學習,采用項目教學培養學生的崗位技能、學習能力和職業素養。…

iOS Core Data 本地數據庫 使用詳解:從模型關系到數據操作

一、引言:Core Data,在本地數據持久化中的地位在 iOS 開發中,本地數據存儲幾乎是每一個 App 都繞不開的問題。無論是緩存用戶信息、離線瀏覽內容,還是記錄用戶操作歷史,一個合適的數據持久化方案都能大大提升應用的體驗…

Java-79 深入淺出 RPC Dubbo 動態路由架構詳解:從規則設計到上線系統集成

點一下關注吧!!!非常感謝!!持續更新!!! 🚀 AI篇持續更新中!(長期更新) AI煉丹日志-30-新發布【1T 萬億】參數量大模型!Kim…

Linux內核中動態內存分配函數解析

在C語言中,動態內存分配通常用于在運行時申請內存。在內核編程中,動態內存分配與用戶空間有所不同,因為內核需要更謹慎地處理內存,且不能使用用戶空間的庫(如glibc)。下面我們將詳細分析Linux內核中動態申請…

Next.js 中配置不同頁面布局方案

在 Next.js 應用中,你可以通過多種方式實現某些頁面全屏、某些頁面帶菜單/頁眉/頁腳的需求。以下是幾種實現方案: 方案一:使用多個布局組件 1. 創建不同的布局組件 // app/default-layout.tsx import Header from /components/header; import…

Spring Boot 使用外置 Servlet 容器:從配置到部署全指南

在 Spring Boot 開發中,我們通常使用嵌入式 Servlet 容器(如 Tomcat),它能將應用打包成可執行 JAR,簡化部署流程。但在某些場景下(如需要支持 JSP、復雜的容器定制或企業級部署規范)&#xff0c…

借助AI學習開源代碼git0.7之九diff-files

借助AI學習開源代碼git0.7之九diff-files diff-files.c 是一個用于比較工作目錄中的文件和 Git 索引(暫存區)中文件的工具。 實質上,它是 git diff命令在不指定特定提交時功能的核心實現。 主要功能分析: 1. 核心功能 diff-files …

社區資源媒體管理系統設計與實現

社區資源媒體管理系統設計與實現 1. 系統概述 社區資源媒體管理系統是一個專為社區戶外廣告打造的高效、專業化平臺,旨在實現社區媒體的數字化管理、智能投放和便捷交易。該系統將整合社區各類廣告資源,為廣告主、物業公司和社區居民提供一站式服務。 1.…

12.1.6 weak_ptr

weak_ptr weak_ptr會指向一個share_ptr&#xff08;使用一個share_ptr來初始化weak_ptr&#xff09;&#xff0c;但并不會增加這個share_ptr的引用計數器&#xff0c;其析構也不會減少share_ptr的引用計數器。 構造函數及使用 #include <iostream> #include <memory&g…