鍍金池/ 教程/ Java/ 并發(fā)性與多線程介紹
并發(fā)新特性—信號量 Semaphore
線程間協(xié)作:wait、notify、notifyAll
notify 通知的遺漏
notifyAll 造成的早期通知問題
多線程的實現(xiàn)方法
深入 Java 內(nèi)存模型(1)
多線程環(huán)境下安全使用集合 API
并發(fā)新特性—Lock 鎖與條件變量
生產(chǎn)者—消費者模型
深入 Java 內(nèi)存模型(2)
線程中斷
Volatile 關(guān)鍵字(上)
并發(fā)新特性—阻塞隊列與阻塞棧
可重入內(nèi)置鎖
守護線程與線程阻塞
并發(fā)新特性—障礙器 CyclicBarrier
Volatile 關(guān)鍵字(下)
synchronized 關(guān)鍵字
synchronized 的另個一重要作用:內(nèi)存可見性
并發(fā)新特性—Executor 框架與線程池
并發(fā)性與多線程介紹
死鎖
實現(xiàn)內(nèi)存可見性的兩種方法比較:synchronized 和 Volatile
線程掛起、恢復與終止

并發(fā)性與多線程介紹

在過去單 CPU 時代,單任務在一個時間點只能執(zhí)行單一程序。之后發(fā)展到多任務階段,計算機能在同一時間點并行執(zhí)行多任務或多進程。雖然并不是真正意義上的“同一時間點”,而是多個任務或進程共享一個 CPU,并交由操作系統(tǒng)來完成多任務間對 CPU 的運行切換,以使得每個任務都有機會獲得一定的時間片運行。

隨著多任務對軟件開發(fā)者帶來的新挑戰(zhàn),程序不在能假設獨占所有的CPU時間、所有的內(nèi)存和其他計算機資源。一個好的程序榜樣是在其不再使用這些資源時對其進行釋放,以使得其他程序能有機會使用這些資源。

再后來發(fā)展到多線程技術(shù),使得在一個程序內(nèi)部能擁有多個線程并行執(zhí)行。一個線程的執(zhí)行可以被認為是一個 CPU 在執(zhí)行該程序。當一個程序運行在多線程下,就好像有多個 CPU 在同時執(zhí)行該程序。

多線程比多任務更加有挑戰(zhàn)。多線程是在同一個程序內(nèi)部并行執(zhí)行,因此會對相同的內(nèi)存空間進行并發(fā)讀寫操作。這可能是在單線程程序中從來不會遇到的問題。其中的一些錯誤也未必會在單 CPU 機器上出現(xiàn),因為兩個線程從來不會得到真正的并行執(zhí)行。然而,更現(xiàn)代的計算機伴隨著多核CPU的出現(xiàn),也就意味著不同的線程能被不同的 CPU 核得到真正意義的并行執(zhí)行。

如果一個線程在讀一個內(nèi)存時,另一個線程正向該內(nèi)存進行寫操作,那進行讀操作的那個線程將獲得什么結(jié)果呢?是寫操作之前舊的值?還是寫操作成功之后的新值?或是一半新一半舊的值?或者,如果是兩個線程同時寫同一個內(nèi)存,在操作完成后將會是什么結(jié)果呢?是第一個線程寫入的值?還是第二個線程寫入的值?還是兩個線程寫入的一個混合值?因此如沒有合適的預防措施,任何結(jié)果都是可能的。而且這種行為的發(fā)生甚至不能預測,所以結(jié)果也是不確定性的。

Java 的多線程和并發(fā)性

Java 是最先支持多線程的開發(fā)的語言之一,Java 從一開始就支持了多線程能力,因此 Java 開發(fā)者能常遇到上面描述的問題場景。這也是我想為 Java 并發(fā)技術(shù)而寫這篇系列的原因。作為對自己的筆記,和對其他 Java 開發(fā)的追隨者都可獲益的。

該系列主要關(guān)注 Java 多線程,但有些在多線程中出現(xiàn)的問題會和多任務以及分布式系統(tǒng)中出現(xiàn)的存在類似,因此該系列會將多任務和分布式系統(tǒng)方面作為參考,所以叫法上稱為“并發(fā)性”,而不是“多線程”。