Java併發編程之背景知識

操做系統發展回顧


裸機

老早以前的計算機只有一個處理器,而一個處理器在同一時刻只能處理一條指令,換句話說,咱們的代碼須要一行一行的按順序被計算機執行,計算機只能把一個程序完整的執行完,而後再執行第二個程序。因此計算機專業的同窗們要排隊去機房作實驗,一我的執行完然他的程序後,第二我的再執行本身的程序,這也就意味着全部計算機資源是被一個程序獨佔的,計算機資源包括處理器、內存、硬盤、輸入/輸出設備啥的。這樣的計算機系統咱們稱之爲裸機。java


簡單批處理系統

後來人們發現對於價格高昂的計算機設備來講,在換人的過程當中就浪費了好多時間,時間就是金錢,有這些時間能夠多執行好多程序了。因此有人寫了一個程序,把全部同窗們須要作實驗的程序都放在這個程序裏排個隊,由這個程序來協調各個同窗們的程序執行,一個執行完了當即換成另外一個,這樣就不用人工干預了,因此他們把這樣的系統叫作簡單批處理系統,而那個負責協調各個童鞋們程序的程序,就是所謂的操做系統的雛形。編程


多道批處理系統

咱們知道,處理器的速度是嗖嗖的,比內存訪問的速度快好多個數量級,而內存又比硬盤、打印機等I/O設備啥的快好多個數量級,而程序執行過程當中又免不了從硬盤裏讀個文件,往打印機輸出個啥的,因此處理器浪費了好多時間等待這些I/O操做的完成。再一次,時間就是金錢,爲了儘量的剝削計算機的運算能力,在程序遇到I/O操做或者什麼其餘會阻塞程序執行的操做時,處理器會轉向執行其它的程序,何時這個阻塞的操做完成了,再掉過頭繼續執行它。從宏觀上看,處理器能夠各個程序輪流執行,因此這樣的系統就稱爲多道批處理系統。windows


分時處理

有的同窗對排隊執行程序這個事兒頗有意見,你們都是學生,憑啥先執行你的後執行個人,你要是寫了個while(true),那你們都得玩兒完~因此人們給每一個程序都分配一點處理器時間去輪流執行,每一個程序分配到的執行時間就叫作時間片,這個過程也叫作分時處理。又由於處理器速度太快了,時間片的大小能夠作到微秒毫秒的大小,因此這個切換的過程對於人來講根本感受不出來,因此看起來像各個程序在同時執行。不事後來人們在一臺計算機上又裝了多個處理器,就是咱們常據說的4核、8核啥的,因此也可能真正的在同時執行。微信

而時間片具體設置爲多大,處理器怎麼切換各個程序的執行,這些工做就是所謂的操做系統來控制的。併發


進程

進程的概念和特色

咱們本身寫的程序,也就是所謂的用戶程序是由操做系統來管理的,人們把一個執行着的程序叫作一個進程(英文名:Process),每一個進程都有這麼兩個特色:網站

1.資源全部權spa

程序在運行過程當中須要必定的資源,好比內存、I/O啥的,這些東西不能在不一樣進程間共享,假如一個進程佔了另外一個進程的內存,那另外一個進程的數據不就丟失了麼;一個進程正在使用打印機輸出東西,另外一個進程也使用的話,不就尷尬了麼。因此進程所擁有的這些資源是不能共享的,而這種資源分配的活是由操做系統來管理的。操作系統

2.調度/執行線程

操做系統會爲它管理的進程分配時間片,來調度哪一個進程應該被處理器處理,哪一個應該先休息一下子。code

因此咱們如今電腦裏每一個運行着的程序都是一個進程,能夠打開你的任務管理器(windows)或者活動監視器(mac),看到咱們的電腦裏其實有好多好多進程喔,什麼QQ、微信、音樂播放器、視頻播放器啥的。

進程的狀態

在操做系統級別上,進程根據它運行的狀況,能夠分紅下邊5種狀態:

1.新建

剛剛建立的那個時刻,操做系統會爲這個進程在內存中建立相應的數據,好比分配這個進程的ID,優先級什麼的~這個狀態持續的時間比較短。

2.就緒

一旦該進程相關的一些數據建立好了,這個進程就會被放在一個叫就緒隊列的隊列裏,以後操做系統就會從這個隊列裏挑一個進程放處處理器裏執行。

3.運行

這個進程被操做系統分配了時間片,處理器開始執行它。

4.阻塞

在執行進程的過程當中,可能遇到某些阻塞的動做,好比I/O操做,處理器若是一直等待該阻塞動做完成的話就太浪費時間了,因此會把等待阻塞動做完成的進程放到一個叫阻塞隊列的隊列裏,以後並不會從這個隊列裏挑選即將執行的進程,而是直到該阻塞動做完成,才從新把該進程放到就緒隊列裏等待執行。

5.退出

該進程執行完畢,或者遇到了什麼錯誤,或者操做系統就是想弄死它,它就被殺死了,這個狀態裏操做系統可能還會記錄一下死因啥的,這個過程也很短。

這些狀態的具體轉換過程看下圖:

clipboard.png

串行編程和並行編程

到目前爲止,咱們的編程模式都是串行編程,也就是處理器執行完一條指令再執行另外一條。舉個例子啊,好比你媽給你佈置了兩個任務:一是去打瓶醬油,二是去燒一壺水,按照串行編程的方式就是兩個任務依次進行,也就是說你先打醬油,而後回來再燒水。這麼作沒啥問題,可是沒有效率啊,因此你也能夠先把水燒上,而後去打醬油,回來正好水燒開了~這種多個任務同時進行的編程方式就叫作並行編程。

回到計算機中來,串行編程的方式就是咱們把全部要完成的任務放到一個進程中去執行,而並行編程的方式就是咱們去開幾個進程同時執行(注:這個同時多是假的,若是隻有單個處理器,那就是看上去是同時的)。這種並行編程的優點是顯而易見的:

1.充分利用多個處理器

現代計算機的處理器愈來愈多,不用白不用。若是全部的任務都塞到1個進程中,而計算機實際有100個處理器,那麼將會有99%的計算能力將被浪費。

2.防止任務的阻塞

即便是在單個處理器中,爲多個任務建立多個進程也是有好處的。先執行的任務可能會須要執行某些I/O操做而形成阻塞,因此就須要等待I/O操做完成才能繼續執行。可是若是爲每一個任務建立一個進程以後,一個任務阻塞掉並不會影響別的任務的正常執行。

3.簡化編程的模型

把一個大任務拆分紅若干個小任務天然是會事情清晰許多(注:也不是絕對啊),也就是所謂的大事化小,小事化了~因此把各個任務分配到不一樣進程裏去執行在咱們編程方面也會容易一些(注:不是絕對啊)。

線程

線程的概念

進程是個好東西,能夠給每一個任務都分配一個進程以達到併發執行的目的。但是運行了一段時間人們發現仍是有一些很差的地方的:

1.不一樣進程之間的資源不可以共享。

這個對於爲了一個大目標細分紅的若干小任務很不友好。比方說對於一個網站來講,針對每個訪問網站的鏈接都去建立一個進程,若是咱們想累加一下總的訪問鏈接數就比較麻煩了,由於各個進程不能去修改同一塊內存。

2.建立、切換、銷燬進程成本太大。

因爲咱們的主題是java語言裏的併發操做,至於操做系統底層對於建立、切換、銷燬進程都要作哪些東西不是咱們嘮叨的範圍,可是這些操做的開銷真的很大,你知道這一點就行了~

再返回頭來看進程的兩個特色,一是對資源的全部權,二是能夠做爲操做系統調度和執行的單位,這兩個特色是沒有關係的,也就是說獨立的,現代的好多操做系統已經把這兩個特色給拆開了,能夠被調度和執行的單位一般被稱做線程或者輕量級進程,而擁有資源全部權的單位一般被稱爲進程。

小貼士:
因爲歷史緣由,原先的進程既是資源的分配單位,也是調度和執行的單位,因此咱們打開一個程序就至關於打開一個進程。
提出線程概念以後,這種打開一個程序就至關於打開一個進程的叫法也被保留了下來。其實如今打開一個程序的意思是打開一個進程而且打開若干個於這個進程相關聯的線程
線程的特色.

線程的特色

看一下這個線程的各類特色

1.一個進程至少對應一個線程

操做系統每開始執行一個程序,都會爲其分配所需的資源以及建立若干個程序執行流,也就是說會建立一個進程以及若干線程。

2.各個線程能夠共享同一個進程中的各類資源

由於線程是從屬於某個進程,因此進程中的內存、I/O啥的資源這個線程均可以訪問到。接着上邊那個例子,咱們能夠對於每個連到網站的鏈接均可以分配一個線程,而後在申請一起內存表示鏈接數,每建立一個線程都把鏈接數加1,問題就愉快的解決了。

3.建立、切換、銷燬線程的成本遠低於原先進程的成本

由於只是一個調度和執行的單位,原本就是原先進程概念的一部分,因此建立、切換、銷燬線程的成本就小多了。

4.線程通訊比進程通訊的效率高

原先進程間通訊須要配合各類機制,如今線程間因爲能夠共享內存,因此通訊就easy多了。

至於進程間通訊須要啥機制我這就不說了,不是咱們討論的範圍。
因此線程的提出完美的解決了一開始提出的把不一樣任務分配給不一樣進程執行的缺陷,如今咱們能夠把不一樣的任務分配給不一樣的線程去執行,不只能夠方便通訊交流,並且建立和使用的成本還低~

線程的狀態

因爲線程只是單純的繼承了進程中調度和執行的特性,因此原先進程擁有的狀態,如今線程同樣擁有,也就是:建立就緒執行阻塞退出

總結

因爲本篇比較簡單,總結就免了。

相關文章
相關標籤/搜索