為什么需要學習并發編程?
并發編程的掌握過程并不容易。我相信為了解決這個問題,你也聽別人總結過并發編程的第一原則,那就是不要寫并發程序。這個原則在我剛畢業的那幾年曾經是行得通的,那個時候多核服務器還是一種奢侈品,系統的并發量也很低,借助數據庫和類似Tomcat這種中間件,我們基本上不用寫并發程序。或者說,并發問題基本上都被中間件和數據庫解決了。
但是最近幾年,并發編程已經慢慢成為一項必備技能。
這主要是硬件的驅動以及國內互聯網行業的飛速發展決定的,現在64核的服務器已經飛入尋常百姓家,大型互聯網廠商的系統并發量輕松過百萬,傳統的中間件和數據庫已經不能為我們遮風擋雨,反而成了瓶頸所在。
于是,并發編程最近幾年成為非常熱門的領域,人才稀缺。但與此同時,關于并發編程的書籍也漸漸豐富起來了。所以當極客時間團隊和我聊這個專欄的時候,我的第一個疑問就是目前市面上已經有很多這方面的圖書了,而且很多都非常優秀,是否還有必要搞一個這樣的專欄。
但是深入想過之后,我堅定了寫作的信心。這些年接觸的大部分同學,都是工作幾年后很多技術突飛猛進,卻只有并發編程成為瓶頸,雖然并發相關的類庫他們也熟悉,卻總是寫不出正確、高效的并發程序,原因在哪里?我發現很多人是因為某個地方有了盲點,忽略了一些細節,但恰恰是這些細節決定了程序的正確性和效率。
而這個盲點有時候涉及對操作系統的理解,有時候又涉及一點硬件知識,非常復雜,如果要推薦相關圖書,可能要推薦好幾本,這就有點“大炮打蚊子”的感覺了,效率很差。同時圖書更追求嚴謹性,卻也因此失掉了形象性,所以閱讀的過程也確實有點艱辛。
我想,如果能夠把這些問題解決,那么做這個事情應該是有意義的。
例如,Java里synchronized、wait()/notify()相關的知識很瑣碎,看懂難,會用更難。但實際上synchronized、wait()、notify()不過是操作系統領域里管程模型的一種實現而已,Java SDK并發包里的條件變量Condition也是管程里的概念,synchronized、wait()/notify()、條件變量這些知識如果單獨理解,自然是管中窺豹。但是如果站在管程這個理論模型的高度,你就會發現這些知識原來這么簡單,同時用起來也就得心應手了。
管程作為一種解決并發問題的模型,是繼信號量模型之后的一項重大創新,它與信號量在邏輯上是等價的(可以用管程實現信號量,也可以用信號量實現管程),但是相比之下管程更易用。而且,很多編程語言都支持管程,搞懂管程,對學習其他很多語言的并發編程有很大幫助。然而,很多人急于學習Java并發編程技術,卻忽略了技術背后的理論和模型,而理論和模型卻往往比具體的技術更為重要。
此外,Java經過這些年的發展,Java SDK并發包提供了非常豐富的功能,對于初學者來說可謂是眼花繚亂,好多人覺得無從下手。但是,Java SDK并發包乃是并發大師Doug Lea出品,堪稱經典,它內部一定是有章可循的。那它的章法在哪里呢?
其實并發編程可以總結為三個核心問題:分工、同步、互斥。
所謂分工指的是如何高效地拆解任務并分配給線程,而同步指的是線程之間如何協作,互斥則是保證同一時刻只允許一個線程訪問共享資源。Java SDK并發包很大部分內容都是按照這三個維度組織的,例如Fork/Join框架就是一種分工模式,CountDownLatch就是一種典型的同步方式,而可重入鎖則是一種互斥手段。
當把并發編程核心的問題搞清楚,再回過頭來看Java SDK并發包,你會感覺豁然開朗,它不過是針對并發問題開發出來的工具而已,此時的SDK并發包可以任你“盤”了。
而且,這三個核心問題是跨語言的,你如果要學習其他語言的并發編程類庫,完全可以順著這三個問題按圖索驥。Java SDK并發包其余的一部分則是并發容器和原子類,這些比較容易理解,屬于輔助工具,其他語言里基本都能找到對應的。
所以,你說并發編程難學嗎?
首先,難是肯定的。因為這其中涉及操作系統、CPU、內存等等多方面的知識,如果你缺少某一塊,那理解起來自然困難。其次,難不難學也可能因人而異,就我的經驗來看,很多人在學習并發編程的時候,總是喜歡從點出發,希望能從點里找到規律或者本質,最后卻把自己繞暈了。
我前面說過,并發編程并不是Java特有的語言特性,它是一個通用且早已成熟的領域。Java只是根據自身情況做了實現罷了,當你理解或學習并發編程的時候,如果能夠站在較高層面,系統且有體系地思考問題,那就會容易很多。
API/SDK Java
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。