溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C#多線程開發(fā)之線程基礎(chǔ)的示例分析

發(fā)布時(shí)間:2021-09-03 13:22:14 來源:億速云 閱讀:124 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)C#多線程開發(fā)之線程基礎(chǔ)的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

    線程基礎(chǔ)

    進(jìn)程是操作系統(tǒng)分配資源的最小單元,線程是操作系統(tǒng)調(diào)度的最小單元” 這句話應(yīng)該學(xué)習(xí)計(jì)算機(jī)的朋友或多或少都聽說過,這在操作系統(tǒng)這門課中是很重要的一個(gè)概念。

    在操作系統(tǒng)中可以同時(shí)運(yùn)行很多個(gè)應(yīng)用程序,那么你知道計(jì)算機(jī)是如何分配和調(diào)度這些應(yīng)用程序去使用CPU進(jìn)行工作的嗎?

    這里面就牽扯到了進(jìn)程、線程的概念,也就是我們接下來要學(xué)習(xí)的內(nèi)容。

    一個(gè)應(yīng)用程序會(huì)有很多個(gè)線程,但是只能有一個(gè)進(jìn)程。也就是說一個(gè)進(jìn)程中可以有很多個(gè)線程。那么這是為什么呢?以前計(jì)算機(jī)只有一個(gè)計(jì)算模塊,每次只能單一的執(zhí)行一個(gè)計(jì)算單元,不能同時(shí)執(zhí)行多個(gè)計(jì)算任務(wù)?,F(xiàn)在隨著科技的發(fā)展,有了多核CPU,可以一次性執(zhí)行多個(gè)應(yīng)用程序,這樣就實(shí)現(xiàn)了多任務(wù)。操作系統(tǒng)為了不讓一個(gè)應(yīng)用程序獨(dú)占CPU,導(dǎo)致其余程序掛起等待,不得不設(shè)計(jì)出一種將物理計(jì)算單元分割為一些虛擬的進(jìn)程,并給予每個(gè)執(zhí)行程序一定量的計(jì)算能力。此外,操作系統(tǒng)必須始終能夠優(yōu)先訪問CPU,并能調(diào)整不同程序訪問CPU的優(yōu)先級(jí)(說白了就是典型的以空間換時(shí)間)。

    線程正是這一概念的實(shí)現(xiàn),可以認(rèn)為線程是一個(gè)虛擬的進(jìn)程,用于獨(dú)立運(yùn)行一個(gè)特定的程序。

    大量使用線程會(huì)消耗大量的OS資源

    那么為什么需要使用線程呢!其實(shí)就是為了在相同的時(shí)間內(nèi),讓操作系統(tǒng)或CPU干更多的活,那么在C#中線程應(yīng)該如何使用或者說在什么場景下使用呢!

    在C#中關(guān)于線程的使用,大多數(shù)時(shí)候是在當(dāng)程序需要處理大量繁瑣、占用資源多、花費(fèi)大量時(shí)間的任務(wù)時(shí)進(jìn)行應(yīng)用,比如訪問數(shù)據(jù)庫,視頻顯示,文件IO操作、網(wǎng)絡(luò)傳輸?shù)取?/p>

    線程在應(yīng)用程序中可以進(jìn)行如何操作:1、創(chuàng)建線程;2、暫停線程;3、線程等待;4、終止線程。

    1、創(chuàng)建線程

    通過聲明并實(shí)例化Thread就可以創(chuàng)建線程,它接收方法作為參數(shù)。使用Thread.Start()就可以開啟子線程,讓其去執(zhí)行方法中的內(nèi)容。

    static void Main(string[] args)
            {            
                //新創(chuàng)建的線程中輸出
                Thread oneThread = new Thread(PrintNumber);
                oneThread.Start();
    
                //主線程中輸出
                PrintNumber();
                Console.ReadKey();
            }
    
            static void PrintNumber() 
            {
                Console.WriteLine("開始......");
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine(i);
                }
            }

    C#多線程開發(fā)之線程基礎(chǔ)的示例分析

    可以看到當(dāng)我們?cè)谧泳€程和主線程中同時(shí)輸出PrintNumber()中的內(nèi)容時(shí),它是亂的隨機(jī)交叉輸出的。

    2、暫停線程

    暫停線程故名思意就是讓線程暫停,不讓其占用CPU資源,在一直等待,啥時(shí)候取消暫停就恢復(fù)運(yùn)行。在C#中暫停就是讓這個(gè)線程進(jìn)入睡眠狀態(tài),讓其休眠,不讓其占用系統(tǒng)資源就可以了。

      Thread.Sleep(TimeSpan.FromSeconds(2));    //睡眠2s

    3、線程等待

    線程等待就是多個(gè)線程在處理某個(gè)任務(wù)時(shí),某個(gè)線程必須等待前一個(gè)線程處理所有數(shù)據(jù)后才可以進(jìn)行執(zhí)行,在這個(gè)期間,這個(gè)線程是阻塞狀態(tài)的。只有前一個(gè)線程完事了,他才可以再繼續(xù)執(zhí)行。

    static void Main(string[] args)
            {            
                //新創(chuàng)建的線程中輸出
                Thread oneThread = new Thread(PrintNumber);
                oneThread.Start();
                oneThread.Join();
    
                //主線程中輸出
                PrintNumber();
                Console.ReadKey();
            }

    也就是說上面的程序主線程必須得等oneThread線程執(zhí)行完P(guān)rintNumber方法后,它才可以執(zhí)行。

    4、線程終止

    就是線程在執(zhí)行過程中,利用某些操作(Thread.Abort())可以使其線程立即退出,不進(jìn)行工作了。

    static void Main(string[] args)
            {            
                //新創(chuàng)建的線程中輸出
                Thread oneThread = new Thread(PrintNumber);
                oneThread.Start();
    
                Thread.Sleep(TimeSpan.FromSeconds(6));
                oneThread.Abort();
    
                //主線程中輸出
                PrintNumber();
                Console.ReadKey();
            }

    上面的程序可以看到,當(dāng)主程序再等待6s后,立即將oneThread線程終止掉。

    其實(shí)Abort()方法是給線程注入了ThreadAbortException方法,導(dǎo)致線程被終結(jié),這其實(shí)很危險(xiǎn),因?yàn)樵摼€程可能正在處理某些重要的數(shù)據(jù),比如接收傳輸數(shù)據(jù)等,這樣子就傳遞摧毀了程序,數(shù)據(jù)也就丟失了。還有就是這個(gè)方法不能保證100%終止線程。有時(shí)候有些異常會(huì)被吃掉,我們可以利用某些關(guān)鍵變量在子線程中進(jìn)行控制,從而取消線程的執(zhí)行就可以。

    在實(shí)際編碼使用線程的過程中,可以通過oneThread.ThreadState來獲取目前線程的狀態(tài)。有時(shí)候我們也可以手動(dòng)的設(shè)置線程的優(yōu)先級(jí),設(shè)置為最高的則提前執(zhí)行,但是這個(gè)只是針對(duì)于單核CPU時(shí),目前市面上基本都是多核的了,這種使用場景也就很少了。

    一般我們創(chuàng)建的線程都是屬于前臺(tái)線程,通過手動(dòng)設(shè)置ontThread對(duì)象的IsBackground屬性為true時(shí)才會(huì)為后臺(tái)線程。通常前臺(tái)線程會(huì)比后臺(tái)線程提前執(zhí)行完。當(dāng)前臺(tái)線程執(zhí)行完成后,程序結(jié)束并且后臺(tái)線程被終結(jié)。進(jìn)程會(huì)等待所有的前臺(tái)線程完成后再結(jié)束工作,但是如果只剩下后臺(tái)線程,進(jìn)程會(huì)直接結(jié)束工作。

    C#中的lock關(guān)鍵字

    某一個(gè)資源當(dāng)被多個(gè)線程同時(shí)訪問時(shí),可能這個(gè)資源的某些值對(duì)于各個(gè)線程來說會(huì)出問題。如果在某一時(shí)刻,一個(gè)線程是使其遞增,一個(gè)線程是遞減,會(huì)導(dǎo)致其值不唯一,各個(gè)線程拿到的值不對(duì)。這種情況就是所謂的競爭條件,競爭條件是多線程環(huán)境中非常常見的導(dǎo)致錯(cuò)誤的原因。

    class PepoleCount 
        {
            int count = 0;
            public void AddCount() 
            {
                ++count;            
            }
            public void DeleteCount() 
            {
                --count;
            }    
        }

    比如是上面的程序,當(dāng)兩個(gè)線程同時(shí)訪問這個(gè)PepoleCount類時(shí),會(huì)導(dǎo)致count變量出現(xiàn)競爭條件。就是每個(gè)線程可能拿到的數(shù)值不是最新的。那么如何辦呢,此時(shí)就需要使用到lock機(jī)制,也就是加鎖。目的是為了當(dāng)一個(gè)線程訪問某個(gè)資源時(shí),其余線程如果在訪問時(shí),必須等待當(dāng)前訪問完事后,它才可以訪問。保證了數(shù)據(jù)的有效性。

    lock關(guān)鍵字是如果鎖定了一個(gè)對(duì)象,需要訪問該對(duì)象的所有其他線程則會(huì)處于阻塞狀態(tài),并等待知道該對(duì)象解除鎖定才可以訪問。

    class PepoleCount 
        {
            private readonly object _syncRoot = new object();
            int count = 0;
            public void AddCount() 
            {
                lock(_syncRoot)
                {
                    ++count;            
                }            
            }
            public void DeleteCount() 
            {
                lock(_syncRoot)
                {
                --count;
                }
            }    
        }

    關(guān)于加鎖這塊還是有很多講究的,不是說每一個(gè)方法,每一個(gè)變量都需要進(jìn)行加鎖,如果頻繁的加鎖會(huì)導(dǎo)致其余線程處于阻塞狀態(tài),那么也會(huì)導(dǎo)致應(yīng)用程序出現(xiàn)嚴(yán)重的性能問題。

    感謝各位的閱讀!關(guān)于“C#多線程開發(fā)之線程基礎(chǔ)的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI