精品秘无码一区二区三区老师-精品秘一区二三区免费雷安-精品蜜桃秘一区二区三区-精品蜜桃秘一区二区三区粉嫩-精品蜜桃一区二区三区-精品蜜臀国产aⅴ一区二区三区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

聊一聊 C#線程池的線程動態(tài)注入

freeflydom
2025年1月3日 9:50 本文熱度 2300

一:背景

1. 講故事

前面二篇我們聊到了 Thread.Sleep 和 Task.Result 場景下的線程注入邏輯,在線程饑餓的情況下注入速度都不是很理想,那怎么辦呢?有沒有更快的注入速度,這篇作為 動態(tài)注入 的終結(jié)篇,我個人總結(jié)如下兩種方法,當然可能有更多的路子,知道的朋友可以在下面留言。

二:提高注入速度的兩種方法

1. 降低GateThread的延遲時間

上一篇跟大家聊過 Result 默認情況下GateThread每秒會注入4個,底層邏輯是由 Blocking.MaxDelayMs=250ms 變量控制的,言外之意就是能不能減少這個變量的值呢?當然可以的,這里我們改成 100ms,參考代碼如下:


        static void Main(string[] args)
        {
            AppContext.SetData("System.Threading.ThreadPool.Blocking.MaxDelayMs", 100);
            for (int i = 0; i < 10000; i++)
            {
                ThreadPool.QueueUserWorkItem((idx) =>
                {
                    Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} -> {idx}: 這是耗時任務(wù)");
                    try
                    {
                        var client = new HttpClient();
                        var content = client.GetStringAsync("https://youtube.com").Result;
                        Console.WriteLine(content.Length);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }, i);
            }
            Console.ReadLine();
        }

現(xiàn)在我們還是用上一篇的方法在如下三個方法 HasBlockingAdjustmentDelayElapsed,PerformBlockingAdjustment,CreateWorkerThread 上埋日志斷點,埋好之后運行程序觀察。

從卦中的輸出結(jié)果看,注入速度明顯快了很多,判斷閾值也從 250ms 變成了 100ms,每秒能注入7~8個線程,所以這是一個簡單粗暴的提速方法。

2. 提高 MinThreads 的閾值

看過上兩篇的朋友應(yīng)該知道,我用過 噴涌而出 四個字來形容前 12個線程,這里的12是因為我的機器是 12 核,言外之意就是為什么要設(shè)置12呢?我能不能給它提升到 120,1200甚至更高的 12000 呢?這樣線程的注入速度不是更快嗎?有了這個想法趕緊上一段代碼,參考如下:


        static void Main(string[] args)
        {
            ThreadPool.SetMinThreads(10000, 10);
            for (int i = 0; i < 10000; i++)
            {
                ThreadPool.QueueUserWorkItem((idx) =>
                {
                    Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} -> {idx}: 這是耗時任務(wù)");
                    Thread.Sleep(int.MaxValue);
                }, i);
            }
            Console.ReadLine();
        }

從卦中看,直接秒了這個 10000 個任務(wù),但不要忘了你的程序此時有1w個線程,如果是32bit程序大概率因為虛擬地址不足直接崩了,如果是 64bit 可能也會導(dǎo)致非常可觀的內(nèi)存占用。

有些人可能對底層邏輯感興趣,我特意花了點時間繪了一張圖來描述底層的運轉(zhuǎn)邏輯。

之所以能快速的產(chǎn)生新線程,核心判斷條件是 numProcessingWork <= counts.NumThreadsGoal ,我們設(shè)置的 MinThread=10000 最后給到了 NumThreadsGoal 字段,所以現(xiàn)有線程數(shù)不超過 10000 的話,就會不斷的調(diào)用 CreateWorkThread 產(chǎn)生新的工作線程。

接下來我們再聊一下 SetMinThreads 這里面的坑吧,如果你將剛才的 ThreadPool.SetMinThreads(10000, 10); 改成 ThreadPool.SetMinThreads(10000, 10000);的話,將不會有任何效果,截圖如下:

為什么會出現(xiàn)這樣的情況呢?這得從源碼上找答案,參考代碼如下:


        public class PortableThreadPool
        {
            private short _minThreads;
            private short _maxThreads;
            private short _legacy_maxIOCompletionThreads;
            private const short DefaultMaxWorkerThreadCount = MaxPossibleThreadCount;
            private const short MaxPossibleThreadCount = short.MaxValue;
            private PortableThreadPool()
            {
                _minThreads = HasForcedMinThreads ? ForcedMinWorkerThreads : (short)Environment.ProcessorCount;
                _maxThreads = HasForcedMaxThreads ? ForcedMaxWorkerThreads : DefaultMaxWorkerThreadCount;
                _legacy_maxIOCompletionThreads = 1000;
            }
        }
        public bool SetMinThreads(int workerThreads, int ioCompletionThreads)
        {
            if (workerThreads < 0 || ioCompletionThreads < 0)
            {
                return false;
            }
            bool flag = false;
            bool flag2 = false;
            this._threadAdjustmentLock.Acquire();
            if (workerThreads > (int)this._maxThreads)
            {
                return false;
            }
            if (ioCompletionThreads > (int)this._legacy_maxIOCompletionThreads)
            {
                return false;
            }
        }

從卦中代碼可以看到 ioCompletionThreads 默認最大值為 1000,如果你設(shè)置的值大于 1000 的話,那前面的 workerThreads 等于白設(shè)置了。。。這就很無語了。。。 如果參數(shù)有誤,你完全可以拋出一個異常來告訴我,,,而不是偷偷的掩埋錯誤信息,導(dǎo)致程序出現(xiàn)了我意想不到的行為。。。

為了湊篇幅,我再說一個有意思的參數(shù) DebugBreakOnWorkerStarvation,它可以用來捕獲 線程饑餓 的第一現(xiàn)場,底層邏輯是C#團隊在代碼里埋了一個鉤子,參考如下:


        private static void GateThreadStart()
        {
            bool debuggerBreakOnWorkStarvation = AppContextConfigHelper.GetBooleanConfig("System.Threading.ThreadPool.DebugBreakOnWorkerStarvation", false);
            while (counts.NumProcessingWork < threadPoolInstance._maxThreads && counts.NumProcessingWork >= counts.NumThreadsGoal)
            {
                if (debuggerBreakOnWorkStarvation)
                {
                    Debugger.Break();
                }
            }
        }

這個 Debugger.Break(); 發(fā)出的 int 3 信號,我們可以用 VS,DnSpy,WinDbg 這樣的調(diào)試器去捕獲,參考代碼如下:


        static void Main(string[] args)
        {
            AppContext.SetSwitch("System.Threading.ThreadPool.DebugBreakOnWorkerStarvation", true);
            for (int i = 0; i < 10000; i++)
            {
                ThreadPool.QueueUserWorkItem((idx) =>
                {
                    Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} -> {idx}: 這是耗時任務(wù)");
                    Thread.Sleep(int.MaxValue);
                }, i);
            }
            Console.ReadLine();
        }

三:總結(jié)

我們聊到了兩種提升線程注入的方法,尤其是第二種讓人意難平,面對上游洪水猛獸般的對線程池進行DDOS攻擊,下游的線程不顧一切,傾家蕩產(chǎn)的去承接,這是一種明知不可為而為之的悲壯之舉。

轉(zhuǎn)自https://www.cnblogs.com/huangxincheng/p/18630175?


該文章在 2025/1/3 9:50:48 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 亚洲国产成人精品无码区二本 | 国产麻豆精品二区视频 | 亚洲丁香五月天缴情综合 | 午夜国产福利看片 | 成人av免费视频在线观看 | 日韩精品无码中文字幕一区二区 | 亚洲精品欧美二区三区中文字幕 | 成视频年人黄网站免费视频 | 四虎最新地址通知www | 海角社区hj4bb | 国产又爽又刺激的视频 | 国产精品激情综合久久 | 精品人妻系列无码人妻漫画 | 国产福利酱国产一区二区 | 女人色极品影院 | 扒开女人下面使劲桶动态图 | 欧美日韩精品视频一区在线观看 | 中国免费无码的网 | 亚洲色无码a片一区二区 | 亚洲国产美女毛片 | 一区二区三区免费视频网站 | 精品无码国产一区二区三区avw | 精品久久久久久中文字幕一区 | 无码一区二区三区曰本a片直播亚洲女人videos一区高潮 | 国产精品第100页 | 日韩精品人妻系列一区二区三区 | 国产日韩中文字幕制服 | 女同久久精品国产99国产精品详情介绍 | 久久久欧美国产精品人妻噜噜 | 亚洲熟女一区 | 99精品国产一区二区三区a片 | 国产成人欧美日韩在线电影 | 国产一区二区精品久久 | 精品麻豆一卡2卡三卡 | 国产三级网在线 | 亚洲地址一地址二地址三 | 国产二级一片内射视频插放 | 亚洲精品午夜久久亚洲精品免费网址 | 精品日本少妇免费 | 偷拍视频精品一区二区三区 | 亚洲国产日本情侣小视频 |