【C#】從 Queue 到 ConcurrentQueue:一次對象池改造的實戰心得

背景

最近在做一個圖像處理的 WPF 項目,底層使用 Halcon 的 HObject 來存放圖像。為了減少頻繁創建和釋放對象帶來的開銷,我實現了一個對象池,用來存放 HObject,方便后續流程復用。

最初的實現用的是 .NET 自帶的 Queue<T>

private readonly Queue<T> objects = new Queue<T>();

配合 lock 實現線程安全,在 GetObject 時取出一個對象,ReturnObject 時放回隊列。

一切看似順利,但隨著功能擴展,我遇到了兩個問題:

  1. 多線程調用時有潛在的性能瓶頸
    lock 保護了隊列,但在高并發下會阻塞其他線程。

  2. 對象生命周期混亂
    在顯示后立即歸還對象時,有時會出現 CurImg 已經被釋放的情況,導致后續流程無法使用。

于是,我開始思考:是不是可以用 ConcurrentQueue 來替代 Queue + lock


Queue vs ConcurrentQueue 對比

特性QueueConcurrentQueue
線程安全? 需要手動加 lock? 內置線程安全
性能在單線程或低并發下更快在多線程下更優,避免鎖競爭
操作方式Enqueue / DequeueEnqueue / TryDequeue
Count 屬性精確(單線程)近似值(多線程下可能不是實時)
適用場景單線程隊列或少量鎖保護的情況高并發讀寫隊列、生產者-消費者模式

改造過程

我將原先的 Queue<T> 換成了 ConcurrentQueue<T>,并去掉了多余的 lock

原始版本(Queue + lock)

public T GetObject()
{lock (objects){if (objects.Count > 0)return objects.Dequeue();elsereturn new T();}
}

改造版本(ConcurrentQueue)

public T GetObject()
{if (objects.TryDequeue(out var obj)){return obj;}return new T();
}

改造后的好處

  1. 線程安全更自然
    ConcurrentQueue 內部使用了無鎖算法,減少了阻塞等待的情況。

  2. 代碼更簡潔
    不再需要手動加 lock,也避免了忘記加鎖導致的潛在 bug。

  3. 性能在多線程下更優
    多個線程可以同時安全地讀寫隊列。


需要注意的坑

改造后,我也踩了幾個坑:

  1. 不要先判斷 Count 再操作
    在多線程下,Count 只是一個快照值。
    如果寫成:

    if (objects.Count > 0)objects.TryDequeue(out var obj);
    

    就可能在判斷到取出之間,隊列已經被別的線程清空,導致邏輯不一致。

    ? 正確寫法:直接用 TryDequeue 判斷并取值。

  2. Count 在容量控制上的延遲
    當多個線程同時 ReturnObject,可能短暫超過 _maxPoolSize
    我的處理方式是用 while 循環清理多余對象:

    while (objects.Count > _maxPoolSize && objects.TryDequeue(out var old))
    {if (old is IDisposable disposable)disposable.Dispose();
    }
    

    雖然會有一點“超限再回落”,但影響不大。


關于 HObject 的思考

在改造過程中,我發現 HObject 這種一次性資源(Dispose 后不可復用)其實不太適合放到傳統意義的“對象池”里。
但是我為了自動化釋放管理,同時不愿意立馬釋放當前圖像,所以這么做了。


總結

從這次改造中,我有幾點心得:

  • 如果是高并發的隊列操作,ConcurrentQueue 是更優解,省去了手動加鎖的麻煩。
  • 多線程下不要依賴 Count 做邏輯判斷,直接用 TryDequeue 更安全。
  • 改造代碼時,不要只關注語法,還要考慮資源生命周期,否則會出現“對象提前被釋放”的問題。

💡 一句話總結

在多線程隊列管理上,ConcurrentQueue 是比 Queue+lock 更簡潔的選擇,但資源的生命周期管理才是對象池真正的難點。

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

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

相關文章

深度解析 AS32S601 芯片 CAN Bus Off 機制:從原理到應用的全流程指南

一、前言在汽車電子、工業自動化等眾多領域&#xff0c;CAN 總線作為一種可靠的通信協議被廣泛應用。而 AS32S601 芯片憑借其卓越的性能和可靠性&#xff0c;在這些領域也發揮著重要作用。其中&#xff0c;CAN Bus Off 功能作為 CAN 總線通信中的關鍵錯誤處理機制&#xff0c;對…

PyCharm Community 2024.2.3.exe 安裝教程(詳細步驟,附安裝包下載)

?1. 下載安裝包? 安裝下載地址&#xff1a;https://pan.quark.cn/s/ca11cb817ee5&#xff0c;你已經下載好了 pycharm-community-2024.2.3.exe 這個文件&#xff08;通常是從 JetBrains 官網下的&#xff09;。雙擊這個 .exe 文件開始安裝。 ?2. 開始安裝向導? 雙擊后&am…

JAVA:SpringBoot 集成 Selenium 實現高效爬蟲

?? 1、簡述 在互聯網數據采集中,傳統基于 Jsoup 或 HttpClient 的爬蟲方案面對復雜 JavaScript 渲染頁面時經常力不從心。此時,Selenium WebDriver 提供了更強大的模擬真實瀏覽器行為能力,成為爬取動態網站的利器。 為了繞過反爬機制,結合 IP 代理池 是提升穩定性和并發…

終端安全檢測和防御技術

目錄 1. 終端安全風險 2. 終端安全檢測和防御技術 3. 網關殺毒技術 3.1 計算機病毒工作步驟 3.2 殺毒防御產品 3.3 網關殺毒功能優勢 3.4 網關殺毒實現方式 4.僵尸網絡檢測和防御技術 4.1 僵尸網絡 4.2 僵尸網絡的形成過程&#xff08;APT場景下&#xff09; 4.3 檢測…

Java緩沖流

字節緩沖流&#xff1a;原理&#xff1a;底層自帶長度為8192的緩沖區提高性能拷貝文件一次讀一個字節一次讀一個字節數組字節緩沖流的讀寫原理字符緩沖流&#xff1a;特定方法字符緩沖輸入流基本寫法輸入所有數據字符緩沖流輸出總結

web服務器tomcat內部工作原理以及樣例代碼

目錄 一、Tomcat 運行原理與 Servlet 機制 1、為什么 Java Web 項目需要 Tomcat 2. 進程模式 vs 線程模式 3、Servlet / Controller 是怎么跟 Tomcat 對接的? 4、java反射與代理機制 ※--高級知識點 (1)原理 (1)樣例:用反射和注解模擬 Tomcat 處理 HTTP 請求時,動…

AI賦能IT服務管理:從被動響應到智能驅動的躍遷

過去十年&#xff0c;IT服務管理&#xff08;ITSM&#xff09;經歷了從紙質工單到數字化平臺的變革&#xff0c;但無論工具多么先進&#xff0c;大多數IT團隊依然面臨著相同的困境&#xff1a;事件處理速度跟不上業務變化人工重復操作占用大量時間數據雖多&#xff0c;卻缺乏可…

云計算-K8s 核心組件之CronJob、RBAC、HPA ,LimitRange、DaemonSet、nodeSelector如何作戰?

目錄 1.CronJob管理 2.RBAC管理 3.HPA管理 4.健康檢查 5.LimitRange管理 6.DaemonSet管理 7.nodeSelector管理 簡介 1. CronJob&#xff08;定時任務控制器&#xff09; 按固定時間間隔&#xff08;類似 Linux cron&#xff09;自動觸發一次性任務&#xff08;Job&#…

數據分析學習總結之實例練習(雙十一淘寶美妝)

本次通過對雙十一淘寶美妝數據的分析實踐&#xff0c;我系統掌握了數據處理與分析的完整流程&#xff0c;從數據初步認知到深度挖掘&#xff0c;再到可視化呈現與結論提煉&#xff0c;收獲頗豐。以下是具體的學習總結&#xff1a;一、數據初步了解&#xff1a;奠定分析基礎在分…

如何評估一個需求的業務價值

要科學、全面地評估一個需求的業務價值&#xff0c;核心在于建立一個多維度的、從戰略到財務、從客戶到風險的“價值羅盤”&#xff0c;并運用這套羅盤&#xff0c;對需求進行系統性的、數據驅動的量化與定性分析。一套成熟的價值評估體系&#xff0c;其構建必須涵蓋五大關鍵視…

day38_2025-08-12

一、 圖像數據的介紹 1.1 灰度圖像 從這里開始我們進入到了圖像數據相關的部分&#xff0c;也是默認你有之前復試班計算機視覺相關的知識&#xff0c;但是一些基礎的概念我仍然會提。 昨天我們介紹了minist這個經典的手寫數據集&#xff0c;作為圖像數據&#xff0c;相較于結構…

Kubernetes1.28-單Master集群部署

一、 服務器環境及初始化 1、架構分析 集群角色主機名操作系統IP地址masterk8s-masterOpenEuler24.03192.168.166.128nodek8s-node1OpenEuler24.03192.168.166.129nodek8s-node2OpenEuler24.03192.168.166.130 2、初始化 所有節點都需要初始化&#xff01; 2.1、清空Iptal…

使用pyqt5實現可勾選的測試用例界面

目錄 界面 代碼 python有哪些自動化測試的庫和html的報告的庫可以和這個軟件結合使用的 **一、自動化測試核心庫** **二、HTML報告生成庫** **三、其他實用工具** **與您的工具結合建議** 參考 界面 代碼 import sys import time import random from PyQt5.QtWidgets import (…

C語言變量的聲明和定義有什么區別?

定義&#xff1a;定義&#xff1a;為變量分配地址和存儲空間聲明&#xff1a;不分配地址和存儲空間一個變量可以在多個地方聲明&#xff0c;但是只在一個地方定義。加入extern修飾的是變量的聲明&#xff0c;說明此變量將在文件或在文件后面部分定義。1.變量聲明作用&#xff1…

imx6ull-驅動開發篇20——linux互斥體實驗

目錄 實驗程序編寫 修改設備樹文件 LED 驅動修改 mutex.c 測試mutexApp.c Makefile 文件 運行測試 在之前的文章里&#xff0c;我們學習了&#xff1a;驅動開發篇16——信號量與互斥體。 本講實驗里&#xff0c;我們來使用互斥體mutex實現 LED 燈互斥訪問的功能&#x…

[4.2-2] NCCL新版本的register如何實現的?

文章目錄1->2->31. ncclRegisterP2pIpcBuffer2. ncclIpcLocalRegisterBuffer(..., 1, 0,...)3. ipcRegisterBuffer(..., regRecord,..., isLegacyIpc)4. p2pProxyRegister()1->2->3 1. ncclRegisterP2pIpcBuffer 在enqueue.cc內的調用是&#xff1a; NCCLCHECK(…

在idea中git切換分支,但是我的文件沒add,沒commit

這是一個很悲傷的故事&#xff0c;我朋友一個下午寫了4個小時的代碼&#xff0c;差不多10多個類&#xff0c;都在切換分支的時候。IDEA發現有沖突&#xff0c;然后就要resolve conflict&#xff0c;發現自己不知道怎么操作&#xff0c;就點了abort & rollback。然后所有代碼…

GPFS api

一、核心命令行 API&#xff08;mm 命令集&#xff09; GPFS 最基礎且常用的接口是命令行工具集&#xff08;以mm為前綴&#xff09;&#xff0c;用于文件系統的創建、配置、管理和監控。這些命令可直接在終端執行&#xff0c;也可通過腳本&#xff08;如 Shell、Python&#…

虛擬機一站式部署Claude Code 可視化UI界面

前言 最近&#xff0c;強大的 AI 編碼助手 Claude Code 在開發者社區中迅速走紅&#xff0c;憑借其出色的代碼生成和理解能力贏得了廣泛贊譽。然而&#xff0c;其純粹基于命令行的交互方式&#xff0c;對于許多習慣了圖形化界面的開發者&#xff0c;尤其是新手而言&#xff0c…

網站IP被劫持?三步自建防護盾

一、劫持檢測實戰&#xff08;Python腳本&#xff09; import requests import socket import ssldef check_hijacking(domain):try:# 獲取真實DNS解析real_ip socket.gethostbyname(domain)# 本地發起請求驗證response requests.get(f"https://{domain}", timeout…