【多線程】基礎理論知識

上一個系列是SpringCloud入門系列,之後確定會寫一期進階系列,可是目前更新的是多線程系列。java

多線程的重要性不用多說,高併發在如今的生活無處不在。618,雙11,12306,支持的併發量那都不知道是多大,說再多遍也不嫌多,是很是很是很是傾佩這些團隊的。算法

本篇文章重點是帶你們瞭解下進程和線程方面的基礎理論知識,涉及到的概念都是簡單可是又很實用的,一些可能沒涉及到的概念也會在後面的文章中寫出來。數據庫

進程

進程的簡單概念

在進程模型中,計算機全部可運行的軟件,一般也包括操做系統,被組織成若干順序進程,簡稱進程(process),一個進程就是一個正在執行程序的示例。

大白話來講,一個進程就至關於咱們啓動的項目,或者說打開任務管理器的時候看到的這些應用都是進程。一個進程主要包括程序計數器、寄存器和變量的當前值編程

這裏還須要講下的一個概念就是守護進程安全

停留在後臺處理的進程稱之爲守護進程。

進程的狀態

進程的狀態有三個狀態,就緒、運行、阻塞。就緒就是能運行,可是還沒運行,CPU被其它進程佔用了;運行就是該時刻進程已經實際佔用CPU在運行了;阻塞基本上等於暫停了,除非有外界因素干擾,否則該進程就不能運行了。多線程

拿作核酸來說,醫護人員就是CPU,正在作核酸的人就是運行態,在後面排隊的就是就緒態,沒有人逼他本身不想作根本沒有來排隊就是阻塞態。併發

值得注意的是,這三種狀態是能夠互相轉換高併發

  • 運行 》》 阻塞: 當系統發現進程沒法再運行下去的時候,或者認爲終止進程後就會發生該轉換。
  • 運行 《 》 就緒: 這兩個轉換大多數時候是一體的,主要是由系統進程調度程序決定的,進程對於調度的變化基本上是感知不到的。當系統認爲這個進程已經長時間佔用CPU了,那麼會根據必定的算法 從新分配CPU的時間片,此時就會伴隨着狀態的轉變。
  • 阻塞 》》就緒: 當進程等待的一個外部事件發生時就會發生次轉換,通俗就是,好比大規模核酸檢測,社區上門提醒,就會去排隊。

進程間的通訊方式

進程間的通訊方式有8種,可是忘記在哪本書上看到的這8種的概念,網上雖然有解釋,可是不太權威,就沒寫出來,各位小夥伴暫時就先了解下是哪8種便可。spa

無名管道,有名管道,高級管道,消息隊列,信號量,信號,共享內存和套接字。操作系統

線程

線程基本概念

對於線程,查了好久也沒有一個明確的概念,甚至再《現代操做系統中》也是模糊的概念,迷你進程(稱爲線程)。

用Java程序通俗的來講呢,就是一個程序就是一個進程,而後main方法就是該進程的主線程,而後在以後咱們會建立多個線程。

咱們知道,每一個進程都有一個地址空間和一個控制線程,這裏的主線程是否是控制線程有待考量。

線程的狀態

相較於進程而言,線程的狀態有五種。

  • New: new是指新建了一個線程,可是還未啓動。對應到代碼就是隻是new了一個Thread後,該線程就處於新建狀態,此時僅由JVM爲其分配內存,並初始化其成員變量的值
  • Runnable: 當線程調用了start()方法後,該線程就處於就緒狀態,在等待cpu時間片。在虛擬機的表現就是Java虛擬機會爲其建立方法調用棧和程序計數器,等待調度運行
  • Running: 顧名思義就是程序處於運行狀態,對應到代碼就是處於就緒狀態的線程得到了CPU,開始執行run()方法的線程執行體,則該線程處於運行狀態。
  • Blocked: 就是咱們常常聽到的阻塞狀態,是指線程由於某種緣由放棄了cpu使用權,即讓出了cpu timeslice(時間片),暫時中止運行。這種狀態會一直維持到線程進入可運行(runnable)狀態,纔有機會再次獲取到cpu時間片,從而再次轉到運行(running)狀態
  • Dead: 線程結束後的狀態就是死亡狀態

對於阻塞狀態而言,分爲3種:

  • 等待阻塞: 運行中的線程中的線程調用了object.wait()方法,JVM會把該線程放入等待隊列中,使得本線程進入阻塞狀態。
  • 同步阻塞: 運行中線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,大白話就是說拿不到鎖,JVM會把該線程放入鎖池(lock pool)中。
  • 其它阻塞: 運行中的線程執行Thread.sleep(long ms)後者t.join()方法,亦或是發出了I/O請求時,JVM會把線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程從新轉入可運行(runnable)狀態。

對於線程的Dead狀態而言,方式有如下三種:

  • 正常結束,就是run()或者call()方法執行完成
  • 異常結束,線程在運行的過程當中拋出一個未捕獲的Exception或Error
  • 調用stop()方法,直接調用該線程的stop()方法來結束線程,可是這種方法容易致使死鎖,因此通常不建議使用

線程間的通訊方式

線程間的通訊方式主要是由3種方式,共享內存、消息傳遞和管道流。

  • 共享內存:java裏面通常是使用volatile共享內存
  • 消息傳遞:java裏面會使用的方式如wait/notify , join 等方法。
  • 管道流:管道輸入/輸出流的形式

其它

進程和線程的區別

多進程就是操做系統中同時運行的多個程序,多線程在同一個進程中同時運行的多個任務。

根本區別:進程是操做系統資源分配的基本單位,而線程是處理器任務調度和執行的基本單位

資源開銷:每一個進程都有獨立的代碼和數據空間(程序上下文),程序之間的切換會有較大的開銷;線程能夠看作輕量級的進程,同一類線程共享代碼和數據空間,每一個線程都有本身獨立的運行棧和程序計數器(PC),線程之間切換的開銷小。

包含關係:若是一個進程內有多個線程,則執行過程不是一條線的,而是多條線(線程)共同完成的;線程是進程的一部分,因此線程也被稱爲輕權進程或者輕量級進程。

內存分配:同一進程的線程共享本進程的地址空間和資源,而進程之間的地址空間和資源是相互獨立的

影響關係:一個進程崩潰後,在保護模式下不會對其餘進程產生影響,可是一個線程崩潰整個進程都死掉。因此多進程要比多線程健壯。

執行過程:每一個獨立的進程有程序運行的入口、順序執行序列和程序出口。可是線程不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制,二者都可併發執行

線程不安全

在《Java併發編程實戰》中有這麼一句話

當多個線程訪問一個類時,若是不用考慮這些線程在運行時環境下的調度和交替進行,而且不須要額外的同步及調用方代碼沒必要做其它的協調,這個類的行爲仍然是正確的,那麼成這個類是線程安全的。

通俗一點來講,要想代碼線程安全,其實就是保證狀態的訪問時不出錯的,對象的狀態通常狀況下指的是數據。可是數據大多數狀況都是共享可變的。

顧名思義,共享指的是線程之間是能夠訪問到這個變量,可變是是指數據的值是能夠被更改的,不是寫死的。

資源

什麼是資源,在《現代操做系統》中的定義是

咱們把這裏須要排他性使用的對象稱爲資源。資源能夠是硬件設備(如藍光驅動器)或者是一組信息(如數據庫中一個加鎖的記錄)......簡單來講, 資源就是隨着時間的推移,必須能得到、使用以及釋放的任何東西

對於這個資源,在java程序裏面是鎖呢,仍是指的共享變量呢,我我的以爲更像是鎖,不知道各位小夥伴怎麼看。

並行和併發

併發是指同一個時間段內多個線程在執行任務,通常是交替執行;並行是指同一個時刻下多個線程同時工做。

在操做系統的層次來看,若是多個線程能同時被多個CPU執行,這樣就是並行。併發是多個線程被一個CPU按照某一算法切換執行

創做不易,若是對你有幫助,歡迎點贊,收藏和分享啦!

下面是我的公衆號,有興趣的能夠關注一下,說不定就是你的寶藏公衆號哦,基本2,3天1更技術文章!!!

相關文章
相關標籤/搜索