第一章  為什么要“千頭萬緒”

資源網絡收集 感謝原創者

轉自http://blog.sina.com.cn/s/blog_5678943c0100d4po.html

本章回答了如下幾個問題:

  ◆ 什么是多任務操作系統?多任務操作系統有哪些類型?它們有何區別?

  ◆ 為什么要使用多線程呢?為什么不使用多進程?線程、進程,它們到底是什么樣的東東?

  ◆ 多線程是如何實現的?線程是如何切換的?效率怎樣?

  ◆ 多線程設計是如此的誘人,難道什么代價也不用付出?怎樣才能很好地進行多線程設計呢?

 

合作型[cooperative]多任務和搶先式[preemptive]多任務有何不同?

兩者的最大區別是誰來把握CPU的分享。前者由程序員的舉止良好才可做到,后者則由操作系統決定,可以強迫應用程序把CPU分享給別人。

Microsoft Windows的前三個版本(1、2、3)屬于合作型多任務操作系統,Windows4.0(即Windows95后均屬于強先式多任務操作系統。

 記住:一個永遠有反映的UIUser Interface)是很重要的。

 線程和進程有何不同?

Win32的角度看,進程擁有內存和資源。資源則包括核心對象(如文件句柄和線程)、用戶資源(如對話框和字符串)、GDI資源(如Device Contextbrushes)。

進程本身并不能夠執行,它只是提供一個安置內存和線程的地方。(進程就是一大堆對象的擁有權的集合。也就是說,進程可以擁有內存上下文、文件句柄、線程及一大串DLL模塊(被載入到這一進程地址空間中)。

進程和內存并沒有真正什么事情。一旦CPU開始執行代碼,你就擁有了一個線程。在同一時間同一進程,你可以擁有一大把線程,執行同一段代碼

 為什么不使用多個進程?

較之進程,線程輕便、價廉,啟動速度快,退出比較快,對系統資源的沖擊比較小。

如果使用多進程,最困難的問題是如何把窗口句柄交給另一個進程。在Win32中,句柄只在其誕生地(進程中)才有意義。這是一種安全警戒,避免某個進程有意無意地危及到另一個進程的資源。

為了分享窗口句柄,你必須明明白白地產生該句柄的一個副本,并且可以被其他進程使用。在一個多線程程序中,所有線程都可以使用這個窗口的句柄,因為句柄和線程生活在同一個進程中。

 如果兩個線程分屬不同的進程,那它們通常沒有辦法共享任何內存。不同進程間如果要通訊,唯有依賴特別的設計,使之擁有共享內存(shared memory)。

如果兩線程屬于同一進程,它們將共享所有的內存(包括全局變量、靜態變量)。

Context SwitchingContext Switch效率

要切換不同的線程,操作系統應先切換該線程所隸屬之進程的內存,然后恢復該線程存放在CONTEXT結構中的寄存器值。此過程稱為context switch

注:CONTEXT結構中保存了該線程上次被打斷時線程當時的狀態,也就是CPU內所有寄存器的內容。

當然,天下沒有免費的午餐,線程切換時都要繳點效率稅金。

對于單CPU而言,搶先式多任務使電腦看起來可以同時處理多個任務。但微觀上看,任一時刻,CPU只能做一件事。

CPU的好處是,CPU越多,就有越多線程可以同時執行,不需要context switch,從而提高了系統效率。

 競爭條件(Race Conditions)和原子操作Atomic Operations

注意在多任務操作系統中,一條C指令一定可以安全執行完畢,而不在乎context switch是否發生。

 好消息與壞消息

使用線程并非沒有代價。采用多線程設計往往會加大程序設計的復雜性,必須做到小心精心安排,才能實現預期目標。

成功的秘訣是小心地規劃:誰要什么?何時要?怎么要?