第一章 為什么要“千頭萬緒”
資源網(wǎng)絡(luò)收集 感謝原創(chuàng)者
轉(zhuǎn)自http://blog.sina.com.cn/s/blog_5678943c0100d4po.html
本章回答了如下幾個問題:
◆ 什么是多任務(wù)操作系統(tǒng)?多任務(wù)操作系統(tǒng)有哪些類型?它們有何區(qū)別?
◆ 為什么要使用多線程呢?為什么不使用多進(jìn)程?線程、進(jìn)程,它們到底是什么樣的東東?
◆ 多線程是如何實現(xiàn)的?線程是如何切換的?效率怎樣?
◆ 多線程設(shè)計是如此的誘人,難道什么代價也不用付出?怎樣才能很好地進(jìn)行多線程設(shè)計呢?
合作型[cooperative]多任務(wù)和搶先式[preemptive]多任務(wù)有何不同?
兩者的最大區(qū)別是誰來把握CPU的分享。前者由程序員的“舉止良好”才可做到,后者則由操作系統(tǒng)決定,可以強迫應(yīng)用程序把CPU分享給別人。
Microsoft Windows的前三個版本(1、2、3)屬于合作型多任務(wù)操作系統(tǒng),Windows4.0(即Windows)95后均屬于強先式多任務(wù)操作系統(tǒng)。
記住:一個永遠(yuǎn)有反映的UI(User Interface)是很重要的。
線程和進(jìn)程有何不同?
從Win32的角度看,進(jìn)程擁有內(nèi)存和資源。資源則包括核心對象(如文件句柄和線程)、用戶資源(如對話框和字符串)、GDI資源(如Device Context和brushes)。
進(jìn)程本身并不能夠執(zhí)行,它只是提供一個安置內(nèi)存和線程的地方。(進(jìn)程就是一大堆對象的擁有權(quán)的集合。也就是說,進(jìn)程可以擁有內(nèi)存上下文、文件句柄、線程及一大串DLL模塊(被載入到這一進(jìn)程地址空間中)。
進(jìn)程和內(nèi)存并沒有真正“做”什么事情。一旦CPU開始執(zhí)行代碼,你就擁有了一個“線程”。在同一時間同一進(jìn)程,你可以擁有一大把線程,執(zhí)行同一段代碼。
為什么不使用多個進(jìn)程?
較之進(jìn)程,線程輕便、價廉,啟動速度快,退出比較快,對系統(tǒng)資源的沖擊比較小。
如果使用多進(jìn)程,最困難的問題是如何把窗口句柄交給另一個進(jìn)程。在Win32中,句柄只在其誕生地(進(jìn)程中)才有意義。這是一種安全警戒,避免某個進(jìn)程有意無意地危及到另一個進(jìn)程的資源。
為了分享窗口句柄,你必須明明白白地產(chǎn)生該句柄的一個副本,并且可以被其他進(jìn)程使用。在一個多線程程序中,所有線程都可以使用這個窗口的句柄,因為句柄和線程生活在同一個進(jìn)程中。
如果兩個線程分屬不同的進(jìn)程,那它們通常沒有辦法共享任何內(nèi)存。不同進(jìn)程間如果要通訊,唯有依賴特別的設(shè)計,使之擁有共享內(nèi)存(shared memory)。
如果兩線程屬于同一進(jìn)程,它們將共享所有的內(nèi)存(包括全局變量、靜態(tài)變量)。
Context Switching及Context Switch效率
要切換不同的線程,操作系統(tǒng)應(yīng)先切換該線程所隸屬之進(jìn)程的內(nèi)存,然后恢復(fù)該線程存放在CONTEXT結(jié)構(gòu)中的寄存器值。此過程稱為context switch。
注:CONTEXT結(jié)構(gòu)中保存了該線程上次被打斷時線程當(dāng)時的狀態(tài),也就是CPU內(nèi)所有寄存器的內(nèi)容。
當(dāng)然,天下沒有免費的午餐,線程切換時都要繳點效率稅金。
對于單CPU而言,搶先式多任務(wù)使電腦看起來可以同時處理多個任務(wù)。但微觀上看,任一時刻,CPU只能做一件事。
多CPU的好處是,CPU越多,就有越多線程可以同時執(zhí)行,不需要context switch,從而提高了系統(tǒng)效率。
競爭條件(Race Conditions)和原子操作(Atomic Operations)
注意在多任務(wù)操作系統(tǒng)中,一條C指令一定可以安全執(zhí)行完畢,而不在乎context switch是否發(fā)生。
好消息與壞消息
使用線程并非沒有代價。采用多線程設(shè)計往往會加大程序設(shè)計的復(fù)雜性,必須做到小心精心安排,才能實現(xiàn)預(yù)期目標(biāo)。
成功的秘訣是小心地規(guī)劃:誰要什么?何時要?怎么要?

