線程線程,進程進程,到底什么是線程,什么是熟練多線程編程?
今天來和大家一起討論討論線程基礎,讓大家知道線程的基本構造。
說線程之前,先要了解下進程,這個可不能不知道。
什么是進程?
Microsoft設計操作系統內核時,他們決定在一個進程中運行應用程序的每一個實例,進程也不過就是個應用程序實例要使用資源的集合。(見過烤玉米,烤甘蔗的沒?如下圖:)
一個進程就好比一個烤筒,一個進程與其他進程互不干涉。操作系統為他們設立了一個虛擬地址空間,確保一個進程使用的代碼和數據無法由另一個進程訪問。這就保證了一個應用程序的健壯性。
現在問題又來了,當一個進程進入無限循環了會怎么樣?
也就是程序沒反應了,無限占用CUP,使CPU不能執行其他任何東西了,所以,進程是健壯(因為不會被破壞,而且也很安全),但還是會引起系統停止響應,也就是我們常說的“死機”。
這時,Microsoft拿出的解決方案就是線程。也就是說,線程運行於進程之中。
講到線程,先來看看什么是線程:
- 線程內核對象, Windows為應用程序所創建的每個線程都有一個線程內核對象,這個對象包含一組對線程進行描述的屬性,除此之外,還包含一個線程上下文(thread context),這個上下文是一個內存塊,這個內存塊用來包含CPU的寄存器集合(什么?你不知道CUP寄存器?火速去百度)。
- 線程環境塊,包含一個內存塊和一個異常處理鏈,還有些本地存儲數據,GDI圖形使用的一些數據結構。個人感覺沒啥用,知道有就行。
- 用戶模式棧,用來用戶的操作帶來的局部變量和實參,好比函數,程序執行到Add(i),那么它在執行函數之前會存下進入函數的地址,然后等函數調用完成之后再返回先前記錄的地址,然后執行下一步。這個用戶模式棧也就這用,要知道的是,Windows最少要為它分配1MB內存。
- 內核模式棧,在用戶模式棧傳遞實參使會用到內核模式棧,調試大家都用過吧? 在調試程序的時候,是不是不能修改代碼了?關鍵就在這,你執行程序之后,用戶模式棧不能訪問內核棧,你寫的代碼都送去內核了。
- DLL線程連接和線程分離通知,用過引用吧?這東西就是你在調用外部程序時需要提前引用一下的原因。加載這個程序,需要用到引用,正如沒有引用,你程序就會出錯。
現在來看看,大家熟悉的任務管理器,對線程來個形象的了解:
看到進程了? 看到線程了?
1個線程占用1MB , 1264個線程就占用1264MB。我就開了個VS 和SQL 兩個大程序。程序開的不多。
再看看每個進程的線程數:
線程數也看到了,SQL-46個線程,最高內存使用。
再來說說 經常遇到的情景,假設你正在玩一個大型游戲,突然老師來了,你要裝作你正在干活,然后Tab+Alt,然后屏幕一黑,急了,怎么還沒跳過去!!快點啊!!
o(∩_∩)o
現在來說說,一個Alt+Tab,Windows做了哪些事。
Windows之所以能快速接收我們的操作,我們覺得是時時在接收我們的輸入,其實,在你不輸入的時候,此線程已經提前終止此線程,而你的輸入,喚醒文本輸入線程只需要5毫秒。
並且這中間還存在一個叫上下文切換的東西,它的切換速度30毫秒,在Windows沒有操作響應的時候,它做的切換工作超乎你的想象,因為有這個功能,保證了Windows的健壯性、快速反應等。
上下文切換,不是看不到的,回到那個情景,Alt+Tab,我們現在都知道它是在執行一個不同的線程,在你切換到桌面的時候,
游戲的線程代碼和數據還在CUP的高速緩存當中(高速緩存能使CPU不需要經常訪問內存,它訪問緩存的速度比內存快得多),你的操作使CPU需要訪問新的數據代碼,而這些代碼在內存中,
所以CPU又要重新讀內存,重新填充告訴緩存,以恢復高速執行狀態。
好了現在我們知道Alt+Tab發生了什么事了。上下文切換所需時間,取決於CPU架構和速度,填充緩存取決於應用程序大小和CPU緩存大小等原因。
以上如有有理解錯誤的地方,請大家提醒指正,謝謝。