日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java并发编程:什么是线程安全,以及并发必须知道的几个概念

發(fā)布時(shí)間:2024/4/17 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java并发编程:什么是线程安全,以及并发必须知道的几个概念 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

廢話

眾所周知,在Java的知識(shí)體系中,并發(fā)編程是非常重要的一環(huán),也是面試的必問(wèn)題,一個(gè)好的Java程序員是必須對(duì)并發(fā)編程這塊有所了解的。為了追求成為一個(gè)好的Java程序員,我決定從今天開(kāi)始死磕Java的并發(fā)編程,盡量彌補(bǔ)自己在這方面的知識(shí)缺陷。

并發(fā)必須知道的概念

在深入學(xué)習(xí)并發(fā)編程之前,我們需要了解幾個(gè)基本的概念。

同步和異步

同步和異步用請(qǐng)求返回調(diào)用的方式來(lái)理解相對(duì)簡(jiǎn)單。

同步:可以理解為發(fā)出一個(gè)請(qǐng)求后,必須等待返回結(jié)果才能執(zhí)行下面的操作。

異步:請(qǐng)求發(fā)出后,不需要等待返回結(jié)果,可以繼續(xù)執(zhí)行后續(xù)操作,異步請(qǐng)求更像是在另一個(gè) “空間” 中處理請(qǐng)求的結(jié)果,這個(gè)過(guò)程不會(huì)影響請(qǐng)求方的其他操作。

舉個(gè)生活中的例子,比如我們?nèi)?shí)體店買(mǎi)衣服,挑選完款式后下單讓售貨員去倉(cāng)庫(kù)拿貨,在售貨員拿貨的過(guò)程你需要在店里等待,直到售貨員把衣服交給你后才算購(gòu)物成功,這就相當(dāng)于同步的過(guò)程。

不過(guò),如果是在網(wǎng)上購(gòu)物的話,我們只需下單并完成支付,對(duì)我們來(lái)說(shuō)整個(gè)購(gòu)物過(guò)程就算完成了。網(wǎng)上的商家接到訂單會(huì)幫我們加緊安排送貨,這段時(shí)間我們可以去做其他的事,比如去外面打個(gè)籃球之類(lèi)的。等送貨上門(mén)并簽收商品就完事了,這個(gè)過(guò)程就相當(dāng)于異步。

并發(fā)和并行

并發(fā)和并行的功能很相似,兩者都可以表示多個(gè)任務(wù)一起執(zhí)行的情況,但本質(zhì)上兩者其實(shí)是有區(qū)別的。

嚴(yán)格意義上來(lái)說(shuō),并行的多任務(wù)是真實(shí)的同時(shí)執(zhí)行,而并發(fā)更多的情況是任務(wù)之間交替執(zhí)行,系統(tǒng)不停的在多個(gè)任務(wù)間切換執(zhí)行,也就是 “串行” 執(zhí)行。

最直接的例子的就是我們的計(jì)算機(jī)系統(tǒng),在單核CPU時(shí)代,系統(tǒng)表面上能同時(shí)進(jìn)行多任務(wù)處理,比如聽(tīng)歌的同時(shí)又瀏覽網(wǎng)頁(yè),但真實(shí)環(huán)境中這些任務(wù)不可能是真實(shí)并行的,因?yàn)橐粋€(gè)CPU一次只能執(zhí)行一條指令,這種情況就是并發(fā),系統(tǒng)看似能處理多任務(wù)是因?yàn)椴煌5那袚Q任務(wù),但因?yàn)闀r(shí)間非常短,所以在我們的感官來(lái)說(shuō)就是同時(shí)進(jìn)行的。而計(jì)算機(jī)系統(tǒng)真實(shí)的并行是隨著多核CPU的出現(xiàn)才有的。

臨界區(qū)

臨界區(qū)表示公共資源或是共享數(shù)據(jù),可以被多個(gè)線程使用。但是每次只能有一個(gè)線程使用它,一旦臨界區(qū)的資源被占用,其他線程就必須等到資源釋放后才能繼續(xù)使用該資源。在Java程序開(kāi)發(fā)中,對(duì)于這樣的資源一般都需要做同步的操作,例如下面的這段代碼,用的就是synchronized關(guān)鍵字來(lái)對(duì)臨界區(qū)資源進(jìn)行同步

public class SyncTest implements Runnable {//臨界區(qū)資源public static SyncTest instance = new SyncTest();@Overridepublic void run() {synchronized (instance) {}}public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(new SyncTest());Thread t2 = new Thread(new SyncTest());t1.start();t2.start();t1.join();t2.join();} } 復(fù)制代碼

阻塞和非阻塞

阻塞和非阻塞通常用來(lái)形容多線程間的相互影響。比如一個(gè)線程占用了臨界區(qū)的資源,那么其他需要這個(gè)資源的線程就必須等待。等待的過(guò)程會(huì)使線程掛起,也就是阻塞。如果臨界區(qū)的資源一直不釋放的話,那么其他阻塞的線程就都不能工作了。

非阻塞則相反,強(qiáng)調(diào)的是線程之間并不互相妨礙,所有的線程都會(huì)不斷嘗試向前執(zhí)行。

死鎖、饑餓和活鎖

這三種情況表示的是多線程間的活躍狀態(tài),對(duì)于線程來(lái)說(shuō),以上的情況都是 “非友好” 的狀態(tài)。

1、死鎖一般是指兩個(gè)或者兩個(gè)以上的線程互相持有對(duì)方所需的資源,并且永遠(yuǎn)在等待對(duì)方釋放的一種阻塞狀態(tài)。例如有兩個(gè)線程A和B同時(shí)共享臨界區(qū)的資源C,當(dāng)A占用C時(shí),B處于阻塞狀態(tài),然而A的釋放需要用到B的資源,這樣一來(lái),就變成了A一直在等待B,B也一直在等待A,互相之間永遠(yuǎn)在等待對(duì)方釋放的狀態(tài)。

一般來(lái)說(shuō),死鎖的發(fā)生是由于程序的設(shè)計(jì)不合理導(dǎo)致,而且死鎖很難解決,最好的方式就是預(yù)防

2、饑餓是指某一個(gè)或者多個(gè)線程因?yàn)榉N種原因無(wú)法獲得所需的資源,導(dǎo)致一直無(wú)法執(zhí)行。比如它的線程優(yōu)先級(jí)太低,而高優(yōu)先級(jí)的線程不斷搶占它所需的資源,導(dǎo)致低優(yōu)先級(jí)資源無(wú)法工作。

3、活鎖的情況是線程一種非常有趣的情況,在生活中我們可能會(huì)碰到這樣的情況,那就是出門(mén)的時(shí)候可能會(huì)遇到有人要進(jìn)門(mén),你打算讓他先進(jìn)門(mén),他又打算讓你先出門(mén),結(jié)果,兩個(gè)人都互相退后了,然后你打算先出門(mén)時(shí)對(duì)方也向前一步,來(lái)來(lái)回回就一直卡在門(mén)口。當(dāng)然,這種事情正常人很快就能解決,但如果是線程碰到就沒(méi)那么幸運(yùn)了。

如果兩個(gè)線程占用著公共的資源,并且秉承著 “謙讓” 的原則,主動(dòng)把資源讓給他人使用,你讓我也讓,這樣就造成資源在兩個(gè)線程間不斷跳動(dòng)但線程之間都拿不到資源的情況,這樣的情況就是活鎖了。

線程安全

線程安全指的是多線程的安全。如果一段程序可以保證被多線程訪問(wèn)后仍能保持正確性,那么程序就是線程安全的。一般來(lái)說(shuō),線程安全注重的是多線程開(kāi)發(fā)中的共享數(shù)據(jù)的安全。就比如下面這段代碼:

public class ThreadSafety implements Runnable{//共享數(shù)據(jù)public static int i = 0;public void increase(){for (int j= 0;j<10; j++){i++;}}@Overridepublic void run() {increase();}public static void main(String[] args) throws Exception{ThreadSafety demo = new ThreadSafety();Thread t1 = new Thread();Thread t2 = new Thread();t1.start();t2.start();t1.join();t2.join();System.out.println(i);}} 復(fù)制代碼

兩個(gè)線程 t1 和 t2 同時(shí)開(kāi)啟,執(zhí)行run方法,在我們的預(yù)想中,如果是線程安全的話,那么main的執(zhí)行結(jié)果應(yīng)該是20,但是因?yàn)?i 是共享數(shù)據(jù),而程序沒(méi)有對(duì) i 的操作做同步的處理,最終運(yùn)行的結(jié)果并不是20,所以這種情況就不是線程安全的情況。

解決的辦法也比較簡(jiǎn)單,可以利用synchronized關(guān)鍵字來(lái)修飾方法或代碼塊,這部分的知識(shí)也是并發(fā)編程中非常重要的一塊,當(dāng)然,本文就不探究了,之后單獨(dú)寫(xiě)篇文章出來(lái)細(xì)說(shuō)。

參考:《實(shí)戰(zhàn)Java:高并發(fā)程序設(shè)計(jì)》

轉(zhuǎn)載于:https://juejin.im/post/5c22f038e51d451d4603291f

總結(jié)

以上是生活随笔為你收集整理的Java并发编程:什么是线程安全,以及并发必须知道的几个概念的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。