大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節(jié)點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 常見問題 學(xué)習(xí)Java并發(fā)編程,教你如何入門

學(xué)習(xí)Java并發(fā)編程,教你如何入門

更新時間:2019-09-07 09:00:00 來源:動力節(jié)點 瀏覽1916次

  Java并發(fā)編程一直是Java程序員必須懂但又是很難懂的技術(shù)內(nèi)容。這里不僅僅是指使用簡單的多線程編程,或者使用juc的某個類。當然這些都是并發(fā)編程的基本知識,除了使用這些工具以外,Java并發(fā)編程中涉及到的技術(shù)原理十分豐富。

  于是乎,就誕生了想寫點東西記錄下,以提升理解和對并發(fā)編程的認知。為什么需要用到并發(fā)?凡事總有好壞兩面,之間的trade-off是什么,也就是說并發(fā)編程具有哪些挑戰(zhàn)?以及在進行并發(fā)編程時應(yīng)該了解和掌握的概念是什么?并發(fā)編程的三大特性是什么?這篇文章主要以這四個問題來談一談。

  一.為什么要用到并發(fā)

  一直以來,硬件的發(fā)展極其迅速,也有一個很著名的"摩爾定律",可能會奇怪明明討論的是并發(fā)編程為什么會扯到了硬件的發(fā)展,這其中的關(guān)系應(yīng)該是多核CPU的發(fā)展為并發(fā)編程提供的硬件基礎(chǔ)。摩爾定律并不是一種自然法則或者是物理定律,它只是基于認為觀測數(shù)據(jù)后,對未來的一種預(yù)測。按照所預(yù)測的速度,我們的計算能力會按照指數(shù)級別的速度增長,不久以后會擁有超強的計算能力,正是在暢想未來的時候,2004年,Intel宣布4GHz芯片的計劃推遲到2005年,然后在2004年秋季,Intel宣布徹底取消4GHz的計劃,也就是說摩爾定律的有效性超過了半個世紀戛然而止。但是,聰明的硬件工程師并沒有停止研發(fā)的腳步,他們?yōu)榱诉M一步提升計算速度,而不是再追求單獨的計算單元,而是將多個計算單元整合到了一起,也就是形成了多核CPU。短短十幾年的時間,家用型CPU,比如Inteli7就可以達到4核心甚至8核心。而專業(yè)服務(wù)器則通常可以達到幾個獨立的CPU,每一個CPU甚至擁有多達8個以上的內(nèi)核。因此,摩爾定律似乎在CPU核心擴展上繼續(xù)得到體驗。因此,多核的CPU的背景下,催生了并發(fā)編程的趨勢,通過并發(fā)編程的形式可以將多核CPU的計算能力發(fā)揮到極致,性能得到提升。

  頂級計算機科學(xué)家DonaldErvinKnuth如此評價這種情況:在我看來,這種現(xiàn)象(并發(fā))或多或少是由于硬件設(shè)計者無計可施了導(dǎo)致的,他們將摩爾定律的責(zé)任推給了軟件開發(fā)者。

  另外,在特殊的業(yè)務(wù)場景下先天的就適合于并發(fā)編程。比如在圖像處理領(lǐng)域,一張1024X768像素的圖片,包含達到78萬6千多個像素。即時將所有的像素遍歷一邊都需要很長的時間,面對如此復(fù)雜的計算量就需要充分利用多核的計算的能力。又比如當我們在網(wǎng)上購物時,為了提升響應(yīng)速度,需要拆分,減庫存,生成訂單等等這些操作,就可以進行拆分利用多線程的技術(shù)完成。面對復(fù)雜業(yè)務(wù)模型,并行程序會比串行程序更適應(yīng)業(yè)務(wù)需求,而并發(fā)編程更能吻合這種業(yè)務(wù)拆分。正是因為這些優(yōu)點,使得多線程技術(shù)能夠得到重視,也是一名Java學(xué)習(xí)者應(yīng)該掌握的:

  充分利用多核CPU的計算能力;

  方便進行業(yè)務(wù)拆分,提升應(yīng)用性能

  二.并發(fā)編程有哪些挑戰(zhàn)

  多線程技術(shù)有這么多的好處,難道就沒有一點缺點或者挑戰(zhàn)么,就在任何場景下就一定適用么?很顯然不是。

image.png

  2.1頻繁的上下文切換

  時間片是CPU分配給各個線程的時間,因為時間非常短,所以CPU不斷通過切換線程,讓我們覺得多個線程是同時執(zhí)行的,時間片一般是幾十毫秒。而每次切換時,需要保存當前的狀態(tài)起來,以便能夠進行恢復(fù)先前狀態(tài),而這個切換時非常損耗性能,過于頻繁反而無法發(fā)揮出多線程編程的優(yōu)勢。通常減少上下文切換可以采用無鎖并發(fā)編程,CAS算法,使用最少的線程和使用協(xié)程。

  無鎖并發(fā)編程:可以參照concurrentHashMap鎖分段的思想,不同的線程處理不同段的數(shù)據(jù),這樣在多線程競爭的條件下,可以減少上下文切換的時間。

  CAS算法:利用Atomic下使用CAS算法來更新數(shù)據(jù),使用了樂觀鎖,可以有效的減少一部分不必要的鎖競爭帶來的上下文切換

  使用最少線程:避免創(chuàng)建不需要的線程,比如任務(wù)很少,但是創(chuàng)建了很多的線程,這樣會造成大量的線程都處于等待狀態(tài)

  協(xié)程:在單線程里實現(xiàn)多任務(wù)的調(diào)度,并在單線程里維持多個任務(wù)間的切換

  由于上下文切換也是個相對比較耗時的操作,所以在"java并發(fā)編程的藝術(shù)"一書中有過一個實驗,并發(fā)累加未必會比串行累加速度要快。可以使用Lmbench3測量上下文切換的時長vmstat測量上下文切換次數(shù)

  2.2線程安全(死鎖)

  多線程編程中最難以把握的就是臨界區(qū)線程安全問題,稍微不注意就會出現(xiàn)死鎖的情況,一旦產(chǎn)生死鎖就會造成系統(tǒng)功能不可用。

image.png

  在上面的這個demo中,開啟了兩個線程threadA,threadB,其中threadA占用了resource_a,并等待被threadB釋放的resource_b。threadB占用了resource_b正在等待被threadA釋放的resource_a。因此threadA,threadB出現(xiàn)線程安全的問題,形成死鎖。同樣可以通過jps,jstack證明這種推論:

image.png

  如上所述,完全可以看出當前死鎖的情況。

  那么,通常可以用如下方式避免死鎖的情況:

  避免一個線程同時獲得多個鎖;

  避免一個線程在鎖內(nèi)部占有多個資源,盡量保證每個鎖只占用一個資源;

  嘗試使用定時鎖,使用lock.tryLock(timeOut),當超時等待時當前線程不會阻塞;

  對于數(shù)據(jù)庫鎖,加鎖和解鎖必須在一個數(shù)據(jù)庫連接里,否則會出現(xiàn)解鎖失敗的情況

  所以,如何正確的使用多線程編程技術(shù)有很大的學(xué)問,比如如何保證線程安全,如何正確理解由于JMM內(nèi)存模型在原子性,有序性,可見性帶來的問題,比如數(shù)據(jù)臟讀,DCL等這些問題(在后續(xù)篇幅會講述)。而在學(xué)習(xí)多線程編程技術(shù)的過程中也會讓你收獲頗豐。

  2.3資源限制的挑戰(zhàn)

  什么是資源限制

  資源限制指在進行并發(fā)編程時,程序的執(zhí)行速度受限于計算機硬件資源或軟件資源。

  硬件資源包括:帶寬的上傳下載速度、硬盤讀寫速度和CPU的處理速度等

  軟件資源包括:線程池大小、數(shù)據(jù)庫的連接數(shù)等

  資源限制引發(fā)的問題

  在并發(fā)編程中,代碼執(zhí)行速度加快的原則是將代碼中的串行部分變成并行執(zhí)行,但有可能由于資源限制問題,導(dǎo)致程序仍按串行執(zhí)行,此時程序不僅不會變快,反而更慢,因為增加了上下文切換和資源調(diào)度的時間。

  如何解決資源限制的問題

  對于硬件資源限制:考慮使用集群方式并行執(zhí)行程序。

  對于軟件資源限制:考慮使用資源池將資源復(fù)用,例如數(shù)據(jù)庫連接池等

  資源限制情況下進行并發(fā)編程

  根據(jù)不同的資源限制調(diào)整程序的并發(fā)度。

  三.應(yīng)該了解的概念

  3.1同步VS異步

  同步和異步通常用來形容一次方法調(diào)用。同步方法調(diào)用一開始,調(diào)用者必須等待被調(diào)用的方法結(jié)束后,調(diào)用者后面的代碼才能執(zhí)行。而異步調(diào)用,指的是,調(diào)用者不用管被調(diào)用方法是否完成,都會繼續(xù)執(zhí)行后面的代碼,當被調(diào)用的方法完成后會通知調(diào)用者。比如,在超時購物,如果一件物品沒了,你得等倉庫人員跟你調(diào)貨,直到倉庫人員跟你把貨物送過來,你才能繼續(xù)去收銀臺付款,這就類似同步調(diào)用。而異步調(diào)用了,就像網(wǎng)購,你在網(wǎng)上付款下單后,什么事就不用管了,該干嘛就干嘛去了,當貨物到達后你收到通知去取就好。

  3.2并發(fā)與并行

  并發(fā)和并行是十分容易混淆的概念。并發(fā)指的是多個任務(wù)交替進行,而并行則是指真正意義上的“同時進行”。實際上,如果系統(tǒng)內(nèi)只有一個CPU,而使用多線程時,那么真實系統(tǒng)環(huán)境下不能并行,只能通過切換時間片的方式交替進行,而成為并發(fā)執(zhí)行任務(wù)。真正的并行也只能出現(xiàn)在擁有多個CPU的系統(tǒng)中。

  3.3阻塞和非阻塞

  阻塞和非阻塞通常用來形容多線程間的相互影響,比如一個線程占有了臨界區(qū)資源,那么其他線程需要這個資源就必須進行等待該資源的釋放,會導(dǎo)致等待的線程掛起,這種情況就是阻塞,而非阻塞就恰好相反,它強調(diào)沒有一個線程可以阻塞其他線程,所有的線程都會嘗試地往前運行。

  3.4臨界區(qū)

  臨界區(qū)用來表示一種公共資源或者說是共享數(shù)據(jù),可以被多個線程使用。但是每個線程使用時,一旦臨界區(qū)資源被一個線程占有,那么其他線程必須等待。

timg (3).jpg

  四.并發(fā)編程的三大特性

  并發(fā)編程有三大特性:原子性、可見性、有序性。

  原子性:是指在一次操作或多次操作中,要么所有的操作都得到執(zhí)行,要么都不執(zhí)行。【類似于事務(wù)】

  JMM只保證了基本讀取和賦值的原子性操作

  多個原子性操作的組合不再是原子性操

  可以使用synchronized/lock保證某些代碼片段的原子性

  對于int等類型的自增操作,可以通過java.util.concurrent.atomic.*保證原子性

  可見性:是指一個線程對共享變量進行了修改,其他線程可以立即看到修改后的值。

  有序性:是指代碼在執(zhí)行過程中的先后順序是有序的。【Java編譯器會對代碼進行優(yōu)化,執(zhí)行順序可能與開發(fā)者編寫的順序不同(指令重排)】

  并發(fā)編程時,保證三大特性的方式有三種:

  1、使用volatile關(guān)鍵字修飾變量

  當一個變量被volatile關(guān)鍵字修飾時,對于共享變量的讀操作會直接在主存中進行,對于共享變量的寫操作是先修改本地內(nèi)存,修改結(jié)束后直接刷到主存中。(未被volatile修飾的變量被修改后,什么時候最新值會被刷到主存中是不確定的)

  2、使用synchronized關(guān)鍵字修飾方法或代碼塊

  synchronized關(guān)鍵字能保證同一時刻只有一個線程獲得鎖然后執(zhí)行同步方法,并且確保鎖釋放之前,會將修改的變量刷入主存。

  3、使用JUC提供的顯式鎖Lock

  Lock能保證同一時刻只有一個線程獲得鎖然后執(zhí)行同步方法,并且確保鎖釋放之前,會將修改的變量刷入主存。

  最后

  本文主要對Java并發(fā)編程開發(fā)需要的知識點作了簡單的講解,這里每一個知識點都可以用一篇文章去講解,由于篇幅原因不能對每一個知識點都詳細介紹,我相信通過本文你會對Java的并發(fā)編程會有更近一步的了解。如果您有哪些不明白,不懂的,可以登錄動力節(jié)點IT培訓(xùn)官網(wǎng),咨詢在線客服老師。

提交申請后,顧問老師會電話與您溝通安排學(xué)習(xí)

免費課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 奇米影视777色 | 国产成人亚洲欧美三区综合 | 日韩美女va在线毛片免费知 | 国产精品99精品久久免费 | 亚洲精品国产免费 | 伊人色综合久久天天网 | 视频一区中文字幕 | 四虎在线视频观看 | 欧美va亚洲va国产综合 | 欧美jizz18性欧美 | 久久精品免观看国产成人 | 伊人久热这里只精品视频 | 成人精品一区二区三区校园激情 | 青青青视频精品中文字幕 | 91精选| 免费爽视频 | 亚洲性片 | 久久er99热精品一区二区 | 国产精品入口麻豆 | 久久久久日韩精品无 | 天天干天天操天天拍 | 国产成人精品高清不卡在线 | 一区二区三区成人 | 奇米色视频 | 在线观看年轻的母亲 | 久久 精品| 亚洲精品乱码国产精品乱码 | 99精品wwxx在线观看 | 亚洲福利一区二区 | 图片亚洲va欧美va国产综合 | 欧美日韩在线精品成人综合网 | 国产成人性毛片 | 性视频一区 | 99久久久无码国产精品 | 久久狠狠婷婷丁香香蕉 | 欧美天天干 | 高清不卡日本v在线二区 | 特级一级毛片视频免费观看 | 亚洲五月色| 黄片毛片在线看 | 爱操在线 |