溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java 并發(fā)編程(一):簡介

發(fā)布時間:2020-06-06 23:57:53 來源:網(wǎng)絡(luò) 閱讀:152 作者:沉默王二 欄目:編程語言

這篇文章的標(biāo)題原本叫做——Java 并發(fā)編程(一):簡介,作者名叫小二。但我在接到投稿時覺得這標(biāo)題不夠新穎,不夠吸引讀者的眼球,就在發(fā)文的時候強(qiáng)行修改了標(biāo)題(也不咋滴)。

小二是一名 Java 程序員,就職于沉默公司,工齡是兩年零一個月零三天。和剛畢業(yè)那會相比,編程能力已經(jīng)大有提升,但領(lǐng)導(dǎo)老王一直沒敢把并發(fā)編程的開發(fā)安排給小二,這讓小二心里耿耿于懷。

這事不怪老王,小二心里很清楚:編寫正確的程序很難,編寫正確的并發(fā)程序更是難上加難。自己功力還不到那個份上,萬一搞砸了,難免讓一向謹(jǐn)慎的老王面上無光。

小二想來想去,辦法只有一個,主動去學(xué)!就找老王要了一本《Java并發(fā)編程實(shí)戰(zhàn)》,據(jù)說這本書是并發(fā)編程中的經(jīng)典之作。拿到書后,隨手翻了翻,竟然發(fā)現(xiàn)里面藏著一封情書:小二激動壞了,想象著老王寫情話的樣子,不由得笑出來聲。

(戛然而止)

小二的背景就先介紹到這。接下來,我們來一起鑒賞下小二讀完這本書后寫下的第一篇文章。

Java 并發(fā)編程(一):簡介

01、為什么需要操作系統(tǒng)

我喜歡在寫文章(不用紙和筆用電腦了)的時候聽音樂(不用 MP3 用電腦了),假如電腦只能做一件事情的話,我就只能在寫完文章的時候再聽音樂,或者聽完音樂的時候再開始寫作,這樣就很不爽——在沒有操作系統(tǒng)前,的確就是這么不爽。

有了操作系統(tǒng)后,情況就變得大不一樣了,電腦可以同時運(yùn)行多個程序。通過 TOP 命令可以查看電腦上當(dāng)前正在運(yùn)行的進(jìn)程(和程序有著密切的關(guān)系),見下圖。

Java 并發(fā)編程(一):簡介

通常情況下,一個程序會至少對應(yīng)一個進(jìn)程。上圖中,“Google Chrome”這三個進(jìn)程意味著我的電腦上打開著一個名叫谷瀏覽器的程序。

讓我們用一段專業(yè)的術(shù)語來描述一下程序和進(jìn)程之間的關(guān)系:

程序是計(jì)算機(jī)為完成特定任務(wù)所執(zhí)行的指令序列。 操作系統(tǒng)允許多道程序并發(fā)執(zhí)行共享系統(tǒng)資源,而程序在并發(fā)執(zhí)行時所產(chǎn)生的一系列特點(diǎn)使得傳統(tǒng)的程序概念已經(jīng)不足以對其進(jìn)行描述,因此,引入了“進(jìn)程(Process)”:可以更好的描述計(jì)算機(jī)程序的執(zhí)行過程,反映操作系統(tǒng)的并發(fā)執(zhí)行、資源共享及用戶隨機(jī)訪問的特性,并以此作為資源分配的基本單位。

每當(dāng)一個程序運(yùn)行時,操作系統(tǒng)就為該程序創(chuàng)建了一個進(jìn)程,并為它分配資源、調(diào)度其運(yùn)行。程序執(zhí)行結(jié)束后,進(jìn)程也就消亡了。一個程序被同時執(zhí)行多次,系統(tǒng)就會創(chuàng)建多個進(jìn)程。因此,一個程序可以被多個進(jìn)程執(zhí)行,一個進(jìn)程也可以同時執(zhí)行多個程序。

當(dāng)然了,對于現(xiàn)在的操作系統(tǒng)來說,進(jìn)程并不是最小的調(diào)度單位,而是線程。線程也被稱為輕量級進(jìn)程。

由于同一個進(jìn)程中的所有線程會共享進(jìn)程的內(nèi)存地址空間,因此這些線程都能訪問相同的變量,如果沒有明確的同步機(jī)制來協(xié)同對共享數(shù)據(jù)的訪問,那么當(dāng)一個線程正在使用某個變量時,另外一個線程可能同時訪問這個變量,就會造成不可預(yù)測的結(jié)果。

02、多線程的優(yōu)勢

查看了一下,我這臺電腦的物理 CPU(處理器)個數(shù)只有一個,但是核數(shù)(一塊 CPU 上面能處理數(shù)據(jù)的芯片組的數(shù)量)是 4 個。

Java 并發(fā)編程(一):簡介

這意味著,我這臺電腦能夠在同一時間處理一個進(jìn)程內(nèi)的四個線程任務(wù):線程 A 正在讀取一個文件,線程 B 正在寫入一個文件,線程 C 正在計(jì)算一個數(shù)值,線程 D 正在進(jìn)行網(wǎng)絡(luò)傳輸。

我們知道,進(jìn)行文件讀寫或者網(wǎng)絡(luò)傳輸通常會發(fā)生阻塞,這也是沒辦法的事。如果沒有多線程的幫助,程序會按照順序依次執(zhí)行,也就意味著發(fā)生阻塞的時候其他任務(wù)只能干巴巴的等著,什么也做不了。

有了多線程,情況就完全不一樣了,線程之間可以互不干擾,從而發(fā)揮處理器的多核能力。

說個有點(diǎn)讓人難為情的事,我是 Eclipse 的(愚)忠實(shí)用戶,至今沒切換到 IDEA 陣營。在用 Eclipse 的時候經(jīng)常會出現(xiàn)這樣的情況,一個進(jìn)度被另外一個卡住,下一個必須等待上一個執(zhí)行完畢才開始執(zhí)行。等待的時候幾乎什么也干不成,點(diǎn)了取消也沒用!

Java 并發(fā)編程(一):簡介

假如 Eclipse 采用多線程的話,每個任務(wù)放在單獨(dú)的任務(wù)中執(zhí)行,響應(yīng)就會快很多。

03、多線程帶來的風(fēng)險(xiǎn)

曾有這樣一則耳熟能詳?shù)墓适隆?/p>

特洛伊人在城外的海灘上發(fā)現(xiàn)了一只巨大的***,他們把它拉進(jìn)了城里而不是把它燒掉或推到海里,以為這是天神給特洛伊人帶來的賜福。于是,特洛伊人歡天喜地,慶祝勝利,他們跳著唱著,喝光了一桶又一桶的酒,以為希臘人被他們戰(zhàn)敗了。

而故事的結(jié)局大家也都知道了。希臘人把特洛伊城掠奪成空,燒成一片灰燼。海倫(宙斯之女,被稱為“世上最美的女人”,她和特洛伊王子私奔,引發(fā)了特洛伊戰(zhàn)爭)也被墨涅依斯帶回了希臘。

Java 并發(fā)編程(一):簡介

多線程帶來了無與倫比的好處,但也潛藏了巨大的風(fēng)險(xiǎn)(就像那個***)。其中尤為突出的就是安全性問題。

public class Unsafe {
  private int chenmo;
  public int add() {
    return chenmo++;
  }
}

上面這段代碼在單線程的環(huán)境中可以正確執(zhí)行,但在多線程的環(huán)境中則不能。遞增運(yùn)算 chenmo++ 可以拆分為三個操作:讀取 chenmo,將 chenmo 加 1,將計(jì)算結(jié)果賦值給 chenmo。兩個線程可能交替執(zhí)行,發(fā)生下圖中的情況,于是兩個線程就會返回相同的結(jié)果。這也是最常見的一種安全性問題。

Java 并發(fā)編程(一):簡介

其次,多線程還會引發(fā)活躍性問題:線程 B 需要等待線程 A 釋放它們共有的資源,而線程 A 由于一些問題導(dǎo)致無法釋放資源,那么線程 B 就只能苦苦地等下去。

再者,多線程還會引發(fā)性能問題(設(shè)計(jì)良好的多線程當(dāng)然會提高性能):當(dāng)線程調(diào)度器臨時掛起一個活躍中的線程轉(zhuǎn)而運(yùn)行另外一個線程時,就會頻繁地出現(xiàn)上下文切換(Context Switch)——開銷很大(掙得多花的也多)。

04、單核 CPU 和多核 CPU

來思考一個問題吧。假如 CPU 只有一個,核數(shù)也只有一個,多線程還會有優(yōu)勢嗎?

閉上眼,讓思維旋轉(zhuǎn)跳躍會。

Java 并發(fā)編程(一):簡介

來看答案吧。

單核 CPU 上運(yùn)行的多線程程序,同一時間只有一個線程在跑,系統(tǒng)幫忙進(jìn)行線程切換;系統(tǒng)給每個線程分配時間片(大概 10ms)來執(zhí)行,看起來像是在同時跑,但實(shí)際上是每個線程跑一點(diǎn)點(diǎn)就換到其它線程繼續(xù)跑。所以效率不會有所提高,線程的切換反到增加了系統(tǒng)開銷。

那多核 CPU 呢?

當(dāng)然有優(yōu)勢了!多核需要多線程才能發(fā)揮優(yōu)勢(不然巧婦難為無米之炊?。?,同樣,多線程要在多核上才能有所發(fā)揮(好馬配好鞍?。?/p>

多核 CPU 多線程不僅善于處理 IO 密集型的任務(wù)(減少阻塞時間),還善于處理計(jì)算密集型的任務(wù),比如加密解密、數(shù)據(jù)壓縮解壓縮(視頻、音頻、普通數(shù)據(jù)等),讓每個核心都物盡其用。

05、最后

親愛的讀者朋友們,小二投稿的第一篇文章到此就結(jié)束了。你對此感到滿意嗎?或者說你期待下一篇嗎?

(此時的小二正在翹首以盼)


上一篇:Java:并發(fā)不易,先學(xué)會用

下一篇:如何保證共享變量的原子性?

微信搜索「*沉默王×××免費(fèi)視頻**」獲取 500G 高質(zhì)量教學(xué)視頻(已分門別類)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI