歡迎光臨
每天分享高質量文章

Java 多執行緒基礎:行程和執行緒之由來

(給ImportNew加星標,提高Java技能)

 

轉自:博客園,作者:Matrix海子

鏈接:www.cnblogs.com/dolphin0520/p/3910667.html

 

現在我們來討論一點稍微難一點的問題:Java併發編程。當然,Java併發編程涉及到很多方面的內容,不是一朝一夕就能夠融會貫通使用的,需要在實踐中不斷積累。由於併發肯定涉及到多執行緒,因此在進入併發編程主題之前,我們先來瞭解一下行程和執行緒的由來,這對後面對併發編程的理解將會有很大的幫助。

 

一.操作系統中為什麼會出現行程?

 

說起行程的由來,我們需要從操作系統的發展歷史談起。

 

也許在今天,我們無法想象在很多年以前計算機是什麼樣子。我們現在可以用計算機來做很多事情:辦公、娛樂、上網,但是在計算機剛出現的時候,是為瞭解決數學計算的問題,因為很多大量的計算通過人力去完成是很耗時間和人力成本的。在最初的時候,計算機只能接受一些特定的指令,用戶輸入一個指令,計算機就做一個操作。當用戶在思考或者輸入資料時,計算機就在等待。顯然這樣效率和很低下,因為很多時候,計算機處於等待用戶輸入的狀態。

 

那麼能不能把一系列需要操作的指令預先寫下來,形成一個清單,然後一次性交給計算機,計算機不斷地去讀取指令來進行相應的操作?就這樣,批處理操作系統誕生了。用戶可以將需要執行的多個程式寫在磁帶上,然後交由計算機去讀取並逐個地執行這些程式,並將輸出結果寫到另一個磁帶上。

 

雖然批處理操作系統的誕生極大地提高了任務處理的便捷性,但是仍然存在一個很大的問題:

 

假如有兩個任務A和B,任務A在執行到一半的過程中,需要讀取大量的資料輸入(I/O操作),而此時CPU只能靜靜地等待任務A讀取完資料才能繼續執行,這樣就白白浪費了CPU資源。人們於是想,能否在任務A讀取資料的過程中,讓任務B去執行,當任務A讀取完資料之後,讓任務B暫停,然後讓任務A繼續執行?

 

但是這樣就有一個問題,原來每次都是一個程式在計算機裡面運行,也就說記憶體中始終只有一個程式的運行資料。而如果想要任務A執行I/O操作的時候,讓任務B去執行,必然記憶體中要裝入多個程式,那麼如何處理呢?多個程式使用的資料如何進行辨別呢?並且當一個程式運行暫停後,後面如何恢復到它之前執行的狀態呢?

 

這個時候人們就發明瞭行程,用行程來對應一個程式,每個行程對應一定的記憶體地址空間,並且只能使用它自己的記憶體空間,各個行程間互不干擾。並且行程儲存了程式每個時刻的運行狀態,這樣就為行程切換提供了可能。當行程暫時時,它會儲存當前行程的狀態(比如行程標識、行程的使用的資源等),在下一次重新切換回來時,便根據之前儲存的狀態進行恢復,然後繼續執行。

 

這就是併發,能夠讓操作系統從宏觀上看起來同一個時間段有多個任務在執行。換句話說,行程讓操作系統的併發成為了可能。

 

註意,雖然併發從宏觀上看有多個任務在執行,但是事實上,任一個具體的時刻,只有一個任務在占用CPU資源(當然是對於單核CPU來說的)。

 

二.為什麼會出現執行緒?

 

在出現了行程之後,操作系統的性能得到了大大的提升。雖然行程的出現解決了操作系統的併發問題,但是人們仍然不滿足,人們逐漸對實時性有了要求。因為一個行程在一個時間段內只能做一件事情,如果一個行程有多個子任務,只能逐個地去執行這些子任務。比如對於一個監控系統來說,它不僅要把圖像資料顯示在畫面上,還要與服務端進行通信獲取圖像資料,還要處理人們的交互操作。如果某一個時刻該系統正在與服務器通信獲取圖像資料,而用戶又在監控系統上點擊了某個按鈕,那麼該系統就要等待獲取完圖像資料之後才能處理用戶的操作,如果獲取圖像資料需要耗費10s,那麼用戶就只有一直在等待。顯然,對於這樣的系統,人們是無法滿足的。

 

那麼可不可以將這些子任務分開執行呢?即在系統獲取圖像資料的同時,如果用戶點擊了某個按鈕,則會暫停獲取圖像資料,而先去響應用戶的操作(因為用戶的操作往往執行時間很短),在處理完用戶操作之後,再繼續獲取圖像資料。人們就發明瞭執行緒,讓一個執行緒去執行一個子任務,這樣一個行程就包括了多個執行緒,每個執行緒負責一個獨立的子任務,這樣在用戶點擊按鈕的時候,就可以暫停獲取圖像資料的執行緒,讓UI執行緒響應用戶的操作,響應完之後再切換回來,讓獲取圖像的執行緒得到CPU資源。從而讓用戶感覺系統是同時在做多件事情的,滿足了用戶對實時性的要求。

 

換句話說,行程讓操作系統的併發性成為可能,而執行緒讓行程的內部併發成為可能。

 

但是要註意,一個行程雖然包括多個執行緒,但是這些執行緒是共同享有行程占有的資源和地址空間的。行程是操作系統進行資源分配的基本單位,而執行緒是操作系統進行調度的基本單位。

 

三.多執行緒併發

 

由於多個執行緒是共同占有所屬行程的資源和地址空間的,那麼就會存在一個問題:

 

如果多個執行緒要同時訪問某個資源,怎麼處理?

 

這個問題就是後續文章中要重點講述的同步問題。

 

那麼可能有朋友會問,現在很多時候都採用多執行緒編程,那麼是不是多執行緒的性能一定就由於單執行緒呢?

 

不一定,要看具體的任務以及計算機的配置。比如說:

 

對於單核CPU,如果是CPU密集型任務,如解壓檔案,多執行緒的性能反而不如單執行緒性能,因為解壓檔案需要一直占用CPU資源,如果採用多執行緒,執行緒切換導致的開銷反而會讓性能下降。

 

但是對於比如交互型別的任務,肯定是需要使用多執行緒的、

 

而對於多核CPU,對於解壓檔案來說,多執行緒肯定優於單執行緒,因為多個執行緒能夠更加充分利用每個核的資源。

 

雖然多執行緒能夠提升程式性能,但是相對於單執行緒來說,它的編程要複雜地多,要考慮執行緒安全問題。因此,在實際編程過程中,要根據實際情況具體選擇。

 

關於行程和執行緒的由來,暫時就講這麼多了,感興趣的朋友可以參考相關資料。

已同步到看一看
赞(0)

分享創造快樂