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

歡迎訪問 生活随笔!

生活随笔

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

java

Java高并发程序设计前言

發(fā)布時間:2024/4/13 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java高并发程序设计前言 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
首先我們先介紹一些基本概念,我們?yōu)槭裁匆褂貌⑿?并行的大環(huán)境是什么樣子的,以及和并行相關(guān)的一些概念,最后我們會介紹兩個和性能,兩個相關(guān)的定律,要有一定的JAVA使用經(jīng)驗,我們首先來探討一個非常重要的問題,為什么我們要寫并行的代碼,并行代碼之所有有這個需求呢,主要是基于兩個原因,第一個是業(yè)務(wù)的要求,比方說,我們有一個服務(wù)器,他要處理多個客戶端的請求,那么一種比較通俗的做法呢,每個客戶端使用一個線程去做,當(dāng)然我們也可以使用一個線程去處理多個客戶端請求,但是這樣我們可能要處理一些客戶端之間的一個調(diào)度問題,那這樣對我們的代碼實現(xiàn)呢,就會有一些復(fù)雜的地方,比如說我們的java虛擬機,當(dāng)我們JAVA虛擬機起來之后呢,JAVA虛擬機在后面運行了好多的線程,其中有一個是啟動我們main函數(shù)的主線程,這些線程共同維護了虛擬機的運作,之所以使用這么多線程的原因呢,是因為我們業(yè)務(wù)模塊上需要,比如及時編譯,他就是為了編譯而存在的,GC線程就是為了做GC而存在的,我們主函數(shù)main線程就是為了運行我們的代碼而存在的,如果沒有線程這個概念,我們不使用并行,我們只能在一個串行的程序當(dāng)中,同時去實現(xiàn)一些功能,比較自然的做交替的,并不是一個執(zhí)行完了,執(zhí)行另外一個,而是會有交叉,如果我們要完成自己來處理,那么會是非常困難的,我們會涉及到很多的任務(wù)調(diào)度等等,那么使用線程呢,他就可以很好地,解決這個問題,調(diào)度的問題呢,交給操作系統(tǒng)去做,對我們應(yīng)用開發(fā)來講呢,只需要簡單的處理一些,業(yè)務(wù)上的模塊就行了,因此使用并行,使用多線程,一個重要的原因呢,業(yè)務(wù)上需要一個執(zhí)行單元,所以為了有這么一個執(zhí)行單元呢,我們很自然的想到了線程這個問題,不用進程,進程太大,你一個進程創(chuàng)建和銷毀的開銷呢,比線程大的多,所以相對來講呢,所以我們就選擇更低消費的一個實體,這個是一個重要的原因,我們主要探討的是第二個原因,就是性能,使用多線程的程序呢,多核CPU的性能呢,一般是要比單線程的性能要好一些,但是對于并行程序,他是好是壞,是利大于弊,其實還是有一些探討的,比如說,大家看這個就是我們的大神

它是linux的創(chuàng)建人,它基于linux系統(tǒng)做了一些修改,來創(chuàng)建linux,所以像這種大神級的任務(wù),他提出了一個什么意見呢,忘掉那該死的并行,他有這么一句話,有多么奇葩的想象力,才能想象并行計算的用武之地,言下之意呢,是說這個并行計算其實就沒有用,其中一個重要的原因呢,并行的代碼要比串行的代碼要多得多,并行的代碼是很難維護的,所以對并行也提出質(zhì)疑,這個東西根本就沒有多大用處,那么事實上是不是這樣子呢,我羅在這里的技術(shù)都討論過,不排除媒體對他斷章取義,因為批評MINIX也道歉了,那么JAVA他也批判過,看到的是JAVA引擎在走下坡路,因為他別無去處,98年的時候說了這句話,2011年的時候說過,我不關(guān)心JAVA,多么可怕的語言,事實上同樣的話用在了C++上面,他說C++是門可怕的語言,他在做git的時候也是用C,并沒有選中C++,包括XML,和Solaris,他都批判過,Solaris很簡單,Solaris是linux的競爭對手,他希望他死掉,那么這個一個對技術(shù)不斷批判的一個人物,他在說并行不行的時候呢

并行計算只有在圖像處理和服務(wù)端編程可以用,并且他在這兩個領(lǐng)域確實有著大量的使用,但是在其他地方,并行計算毫無建樹,事實上他說這句話是很有道理的,因為圖像處理,它是屬于計算密集型的,這個領(lǐng)域,你單個CPU計算可能會有點累,當(dāng)你需要去處理大量的計算的時候呢,能夠明顯提高系統(tǒng)的性能,第二個領(lǐng)域就是服務(wù)端編程,比如服務(wù)器,后臺在運作的一個程序,因為這些程序他往往也需要大量的處理,往往也是計算密集型的,比如你做一個數(shù)據(jù)挖掘,做一些數(shù)據(jù)分析,他也有可能像不同的服務(wù)器去請求數(shù)據(jù),因此呢他在這兩個領(lǐng)域呢,JAVA語言的主要工作場景呢,也就是在服務(wù)端進行,因此呢從這個角度來看,為什么要使用并行呢,是因為業(yè)務(wù)上的原因,第二個呢是并行程序在多核CPU上,確實可以提高性能,在現(xiàn)在這個大環(huán)境下來說,JAVA應(yīng)用到服務(wù)端編程,與并行主要執(zhí)行領(lǐng)域是一致的,用于用戶UI的操作,并行程序,并行多線程,其實對于用戶的價值并不是很大

并行程序流行開來的重要原因呢,多核CPU的產(chǎn)生,為什么會有多核CPU呢,那是因為摩爾定律在單核CPU發(fā)展已經(jīng)失效了,根據(jù)摩爾定律的說法呢,每18個月到24個月,就是一年半到兩年的時間,我們芯片的性能是會提高一倍的,翻一翻,但事實上是什么情況呢,在2004年因特爾就宣布徹底取消了4GHZ的計劃,在他當(dāng)時的基礎(chǔ)上面,他要做一個主頻是4GHZ的芯片呢,他做不出來,現(xiàn)在已經(jīng)是2015年了,現(xiàn)在能夠買的主頻呢,基本上也就是4GHZ多一點點,是到頂了,絕大部分還是留在3.8G,4G以下,4GZ芯片是很少的,而且賣得很貴,而且再往上發(fā)展的可能性呢,看起來也不大,從這里可以看到,10年時間過去了,CPU的主頻,基本上已經(jīng)沒有太大的變化,那么按照摩爾定律,我們?nèi)绻?4個月算的話,那你10年過去了,應(yīng)該翻了5翻,那也應(yīng)該是32倍,如果那個時候能夠達到3G,現(xiàn)在CPU的主頻,按照摩爾定律的說法呢,達到100G也沒問題,實際上我們離100G還有很遠,因此計算機的發(fā)展呢,實際上在這個地方已經(jīng)受到了一個瓶頸,所以摩爾定律在芯片的發(fā)展呢,已經(jīng)失效了,如果計算沒法提高性能,那我們應(yīng)該怎么辦呢,人們就很聰明了,既然你沒有辦法提高你單個CPU的性能,那我們就在一個CPU里面呢,我塞很多的核進去,因此多核CPU就興起了,單核CPU的瓶頸之后,導(dǎo)致我們往多核CPU發(fā)展,這個并不是我們的選擇,而是一條沒有選擇的道路,因為我們做不出來了,預(yù)計將來68核,他也會產(chǎn)生,說不定現(xiàn)在也有,后端也有64核CPU的使用了,如果將來的CPU內(nèi)核越來越多,那么很顯然并行的需求也會越來越大

那我們再來看唐納德他所說的一句話,這也是計算機中的一個頂級科學(xué)家,他說在我看來,這種現(xiàn)象,并發(fā),或多或少是因為硬件設(shè)計者已經(jīng)無計可施了,他們將摩爾定律的責(zé)任呢,推脫給了軟件開發(fā)者,也就是說,因為我沒有辦法提高CPU的主頻,所以那你就去用多個CPU,來做這件事情,換個角度來說,如果我們現(xiàn)在有10G,100G的CPU,其實并行不像現(xiàn)在這么重要,因為我們完全可以寫在一個串行的程序當(dāng)中,他反正是運行的很快,我們也可以降低編程難度,在多核CPU上的可見性,這樣的問題產(chǎn)生了,但是事實上我們沒有,我們沒有這樣的CPU,所以我們不得不去做并行這件事情

這是因為,我們剛才說過的,需要并行是因為業(yè)務(wù)模型的需要

下面來看一下并行的幾個比較重要的概念,這里會介紹同步,異步,并發(fā),并行,臨界區(qū),阻塞和非阻塞,饑餓,活鎖,并行級別的概念

首先我們來看一下同步和異步,同步異步是對方法調(diào)用而言的,如果一個方法調(diào)用是同步的,那在這個時間軸上,我們可以看到,同步調(diào)用呢,它會等待這個方法返回,這個方法實現(xiàn)多久,他就等待多久,異步調(diào)用呢它會瞬間返回,異步他返回很快,異步調(diào)用返回很快,并不表示說你,這個調(diào)用就完成了,它會在后臺啟一個線程,一般都是啟一個線程,慢慢地做他的事情,所以異步調(diào)用呢,是指我一個函數(shù)調(diào)用下去,我馬上就能夠返回,但是我返回之后呢,這個程序我調(diào)用的請求呢并沒有做完,但是我不影響我繼續(xù)做我下面的事情,在我異步調(diào)用之后,還能夠做我下面的其他的事情,我異步調(diào)用的工作內(nèi)容,他在另外一個線程當(dāng)中,慢慢去做,那這就是異步調(diào)用和同步調(diào)用,異步調(diào)用和同步調(diào)用的含義

下面我們來看一下并發(fā)和并行的區(qū)別,一般來說呢,不需要特別區(qū)分并發(fā)和并行,他們有什么特別重要的區(qū)別,因為對我們外界看來呢,并發(fā)和并行他的外在表象,基本上是一致的,并發(fā)他的英文單詞,Concurrency,并行叫做Parallelism,這樣的程序叫做并行,兩個線程,或者兩個進程也好,他們同時在里面執(zhí)行,這叫并行,什么叫并發(fā)呢,并發(fā)是指我一會做這個事情,一會做這件,他有一個調(diào)度的過程,這個叫并發(fā),對于單個CPU來講,他不可能出現(xiàn)并行的情況,單個CPU他同一個時間只能做同一件事情,它是分時的在做調(diào)度,調(diào)度這所有的任務(wù),但是對于多個CPU來講呢,他就是一個并行的,兩個CPU,每個CPU做一件事情,這兩個程序就是并行執(zhí)行,但對于外在表象而言,我們看到這兩件任務(wù)都是同時執(zhí)行的,所以一般來說呢,我們不用特別去關(guān)注,但是在有些場合呢,我們還是需要去確認一下,在 一般來說,這兩個概念對于我們來說呢,是一樣的

下面我們來看一下臨界區(qū),對于多線程程序來講呢,臨界區(qū)是一個非常重要的概念,我們提到臨界區(qū)呢,就表示他是一個公共的區(qū)域,也就是說,所有的線程,他都能夠訪問這個公共的區(qū)域,所有的線程都能夠訪問他,因為所有的線程都能夠訪問他,當(dāng)然多個線程去訪問這個臨界區(qū)呢,那可能會破壞掉,比如你一個人去寫數(shù)據(jù)還沒有寫完,另外一個線程又去里面去寫數(shù)據(jù),那么著兩個數(shù)據(jù)一疊加,就可能會產(chǎn)生錯誤的數(shù)據(jù),因此呢臨界區(qū)呢,它是一個需要被控制的區(qū)域,我希望多個線程進入臨界區(qū),有可能把我數(shù)據(jù)改壞掉,所以每一次我只希望有一個線程可以進去,那當(dāng)線程進去之后呢,其他線程還想進入到臨界區(qū)里面來呢,需要進入阻塞隊列進行等待,等到什么時候為止呢,等待我臨界區(qū)里的線程,釋放了這個鎖,其他可以在等待隊列當(dāng)中呢,再取一個線程,這里講的是臨界區(qū)的控制方法,臨界區(qū)本身就是有共享資源,當(dāng)多線程訪問的時候呢,就關(guān)注他額外不會被破壞的數(shù)據(jù)

下面我們來看一下阻塞和非阻塞,阻塞和非阻塞通常用來形容多線程間的相互影響,如果一個線程占用了臨界區(qū),其他線程不能夠再進去,就是阻塞,因為其他線程要在臨界區(qū)之外做等待,阻塞的含義呢是指線程操作系統(tǒng)層面,被掛起,所以阻塞的方式呢,他一般性能不會太好,根據(jù)一般的統(tǒng)計呢,如果你一個線程在操作層面,把你調(diào)出去了,做了上下文切換了,所以這不是一個特別好的方法,但是是一個非常簡單的方法,所有責(zé)任都推給了操作系統(tǒng),去幫我們調(diào)度,雖然說他的性能不高,能把這件事情做得很好,阻塞它會有一個問題,如果說我有個線程,一直占著不釋放資源,其他要使用臨界區(qū)的資源呢,都會不能工作,都會阻在那邊,那么非阻塞是指允許很多線程同時進入臨界區(qū),那這個就是非阻塞,我一個線程進入臨界區(qū)之后,我該線程也能夠進去,我只要保證不把數(shù)據(jù)改壞,就可以了

下面我們再來看一下死鎖,節(jié)饑餓和活鎖,對于阻塞的程序來講,如果是進入臨界區(qū),就有可能發(fā)生死鎖的現(xiàn)象,比如這四輛小車,就發(fā)生了死鎖,每輛小車所占的一條路呢,我們認為是一個資源,A車把這條路給堵了,B車把這條路給堵了,C車把這條路堵了,D車把這條路堵了,但是A需要這條路,C需要這條路,D需要這條路,B需要這條路,這樣就導(dǎo)致ABCD,沒有人能夠繼續(xù)往下走,除非我們把其中一個給停止掉,就是把D車挪走,C車就能走,B車也能走,A車也能走,這就是死鎖,死鎖就是使得整個程序卡死在里邊,不再提供服務(wù)了,如果我們系統(tǒng)出現(xiàn)了這個問題呢,死鎖雖然說不是一個好現(xiàn)象,但是死鎖它是一個靜態(tài)的一個問題,也就是說一旦發(fā)生死鎖呢,他不會占用CPU,所以這是一個靜態(tài)的問題,相對來講還是比較好分析的,與死鎖相對應(yīng)的還有一個活鎖,活鎖是什么意思呢,我們舉個例子,比方說,我們電梯門開了,電梯門開了之后呢,里面的人要出來,假設(shè)電梯里有一個人,電梯外也有一個人,電梯里面的那個人呢,要出來,電梯外面那個人要進去,那有可能碰到的問題是說,你面對面撞在了一起,你們兩個人把路都堵了,那你可能要避讓他,所以你就往左邊考了一靠,想避開他,他的想法是跟你一樣的了,他也避開你,他就往右邊靠了一靠避開你,因為你們兩個是面對面的,所以你往左邊靠,他往右邊靠的時候呢,你們兩個又把路給堵上了,然而你這個時候發(fā)現(xiàn)不對,所以你又往右邊靠,他發(fā)現(xiàn)不對,他呢再往左邊靠,然后你們又把路給堵上了,與此往復(fù),不停的兩個人,一會往左一會往右,不停的把這個路給堵上,作為人來講,你發(fā)現(xiàn)這種情況呢,我們會停下來,眼神交流一下,或者我們停下來不動,讓另外一個人先過,這個問題又解決了,因為人是有智力的,但是如果這個情況發(fā)生在程序上,發(fā)生在線程上面呢,你就不會這么走運了,一個線程如果他搶占到資源之后,他發(fā)現(xiàn)另外的資源沒有辦法拿到,這個時候他為了避免死鎖,如果死鎖產(chǎn)生的一個必要條件,你搶占了資源而不釋放,如果你搶占了資源而釋放了呢,就沒有死鎖這種說法,因為他沒有辦法拿到所有的資源,因此他把自己釋放的那塊資源也給釋放掉,而這個時候另外一個線程,做了同樣的事情,他們需要相同的資源,比如他們都需要資源A,一個線程搶了資源A,另外一個資源搶了資源B,然而他們發(fā)現(xiàn)都沒法工作,把資源同時釋放掉,釋放了之后呢,他們一看,資源A和資源B都出來了,然后一個線程拿了資源B,另外一個線程拿了資源A,然后一看,我又沒法工作了,然后他們又互相謙讓,又把這個資源放出去,與此反復(fù),這個資源在多個線程之間跳來跳去,活鎖一旦發(fā)生,這個問題就比死鎖更難查,因為它是一個動態(tài)的一個問題,并不是像死鎖那樣,現(xiàn)在就進在里面不動了,線程不停的在動,不停的在重試,但是永遠不能夠成功,或者說要花很長的時間才能夠成功,性能也會受到很大的影響,那就是活鎖,那么有關(guān)饑餓呢,因為某種原因,比如你這個線程優(yōu)先級可能很低,別的線程優(yōu)先級很高,所以在調(diào)度的時候呢,就調(diào)度不到你,結(jié)果操作系統(tǒng)只調(diào)度優(yōu)先級高的線程,因為我優(yōu)先級很低,所以我就調(diào)度不到,我就不能繼續(xù)往下執(zhí)行,這個時候我就會餓死,因為我分不到足夠的資源,那另外的一種情況呢,就比如我們在競爭的時候呢,我競爭這個數(shù)據(jù),原子修改,做這個原子操作,我總是失敗,總是失敗,那么這個時候我也有可能會被餓死,因為我不能往下再走了,這個是多線程當(dāng)中,可能會碰到的一些問題

下面我們再來看幾個重要的概念,有關(guān)并發(fā)的概念,一般并發(fā)呢,阻塞和非阻塞,這個概念我們之前就有講過,對于非阻塞來講呢,我們可以進一步分為無障礙的,無鎖,無等待,下面我們就這幾個級別來做一個講解

下面我們就對這幾個級別來做一個簡單的了解,阻塞就是指一個線程進入臨界區(qū)以后呢,其他線程就必須在這個臨界區(qū)之外進行等待,等這個線程出來之后呢,他們才能夠進去執(zhí)行

第二個就是無障礙,無障礙是非阻塞,他并不要求一個線程進入臨界區(qū)之后,其他線程在外面等待,線程是可以自如的進入臨界區(qū),那么跟阻塞相比呢,認為他是一種悲觀的策略,它會認為說,大家一起修改這個數(shù)據(jù)呢,很有可能把這個數(shù)據(jù)改壞的,所以每次我只能允許一個人去修改,而這個非阻塞調(diào)度呢,相對來講比較樂觀,如果大家一起修改,也未必把這個數(shù)據(jù)改壞,所以我可以放開讓大家都進來,但是它是一種寬進嚴(yán)出的策略,進的時候所有線程都能夠進入臨界區(qū),包括讀也好,寫也好,但是你出來的時候呢,就不一定了,如果他發(fā)現(xiàn)線程,臨界區(qū)的操作呢,跟別人產(chǎn)生了沖突,那么他就會回滾這條數(shù)據(jù),比如我們要去讀取一對坐標(biāo),x,y,坐標(biāo)系統(tǒng)去讀取x,y,他先讀X,再讀Y,當(dāng)他讀到Y(jié)的時候,他發(fā)現(xiàn)有其他的線程,改了我這個X,這個時候他就會認為,我再把這個Y讀出來是沒有用的,我可能會讀到一個錯誤的數(shù)據(jù),所以他就會重試,再去重新的讀取數(shù)據(jù),直到自己讀到的X,Y呢,是沒有問題的,所以他是一個不斷重試的一種策略,所有的線程都相當(dāng)于在,拿去一個系統(tǒng)當(dāng)前的快照,他們會一直嘗試讀取到的快照,有效地為止

第二個級別是無鎖,我們剛剛說的無障礙呢,他是說,我所有的線程都進入臨界區(qū),但是如果發(fā)生了競爭,他并不保證臨界區(qū)當(dāng)中的線程能夠順利的出來,因為如果他發(fā)現(xiàn)自己的數(shù)據(jù)呢,每次讀取或者每次操作,總是跟別人產(chǎn)生了沖突,他就不停的嘗試不停的嘗試,如果有10個線程,線程1他修改了以后,改了部分?jǐn)?shù)據(jù),結(jié)果他被線程2干擾了,線程2被線程3干擾了,依次類推,線程2又干擾了線程10,如果他們之間都是彼此干擾的,最終會導(dǎo)致所有的線程呢,系統(tǒng)的性能會受到比較大的影響,必須在無障礙的上面呢,加上一個約束,無鎖他必須首先是無障礙的,也就是說你所有的線程呢,都必須能夠進入這個臨界區(qū),但是無鎖他加了一個限制條件是說,我保證在我這一次競爭當(dāng)中,有一個線程是必然能勝出的,那這樣他就能夠保證說,臨界區(qū)當(dāng)中的線程呢,至少有一個是能夠順利走出去的,而不至于所有的全在里面陣亡掉,如果至少有一個線程能夠出去,假設(shè)里面有100個線程,第一個線程競爭順利,我們走出了臨界區(qū),其他99個再競爭,因為每次競爭肯定保證有一個能夠勝利,我們再出去一個,剩下98個再競爭,使得你這個系統(tǒng),至少是能夠順暢的進行下去,那這就是無鎖,下面這段代碼是比較典型的在JAVA當(dāng)中,無鎖計算的這么一段代碼,在后面我們無鎖的程序呢,會在我們后續(xù)的課程當(dāng)中呢,感覺鋪天蓋地就是無鎖的計算

我們下面再來看一下無等待,無鎖剛才已經(jīng)講了,它是說,我保證每一次至少有一個線程,它是能夠在有限步當(dāng)中完成操作,那么其他的線程呢,在不停的競爭,知道有一個線程為止,那無等待呢,他就更近一步,所以無等待他要求你首先無鎖,也就是他保證你能進,他要求所有的線程都能夠在有限步上完成,這個要求提的很高,意味著說,你任何線程都能夠進入進去,都能夠無障礙的進入臨界區(qū),并且呢你任何線程呢,都能夠在若干步當(dāng)中,有限步當(dāng)中,離開臨界區(qū),這就會使得你系統(tǒng)的運行呢,會變得非常的順暢,那么無等待可以說是并行最高級別的了,基本上是可以讓每個系統(tǒng)發(fā)揮到最好的效率,那么無等待他必然是無饑餓的,因為你所有的線程,都能夠有限步的完成,因此你不會永久的出不去,所以他一定是無饑餓的,那無等待的一個典型案例呢,就比方說,我們有讀寫兩個線程,如果說我的讀線程,只有讀線程,沒有寫線程,那所有的讀線程之間呢,必然是無等待的,原因很簡單,因為你所有的進程進來,不能進,因為你讀你不會修改數(shù)據(jù),所以數(shù)據(jù)都是一致的,所有的讀都是無等待的,但是說如果你有一個寫在里面,那么由于寫線程會有修改數(shù)據(jù)呢,所以我們可以提供一種算法,比如有一種算法會這樣做,因為我寫會影響到讀,所以我在每次寫之前呢,我把數(shù)據(jù)全部先拷貝一份副本,我僅拿到一份副本,然后我修改這個副本,而不是修改原始數(shù)據(jù),修改數(shù)據(jù)的過程呢,可能需要一點時間,但是由于我修改的是我副本的數(shù)據(jù),而不是你的原始數(shù)據(jù),所以這個修改的過程,也不影響線程沖突,因此在這種情況下呢,讀線程一樣是無等待的,他們都能在有限步中完成操作,所有的寫線程,因為每個線程也都是寫的副本,他們的寫也是無等待的,他們都不需要去做同步,最后需要做同步的是什么呢,只是將寫完之后的數(shù)據(jù)呢,再回寫到覆蓋原始數(shù)據(jù)的,而覆蓋原始數(shù)據(jù)的,是非常非??斓?因為我們不需要做大量的操作,或者是一個指針,或者是一個引用,做一個替換而已,那不管哪個寫線程勝出,總是能夠保證,這個替換上去的數(shù)據(jù)呢,是一致的,并不會像其他的寫的算法一樣,我可能會把自己寫壞,因為大家寫的只是副本,所以必然是安全的,這種方式呢,這個就是等待的一個典型的一個實現(xiàn),當(dāng)然無等待的實現(xiàn)是比較麻煩的,而且他有一些技巧性的東西,相對來講呢,無鎖的使用呢,會更加的廣泛一些

阿姆達爾他還有一個公式,N個處理器時的,這個加速比,等于一個處理器的加速比,這個公式在這里,處理器的個數(shù)是n,我使用N個處理器的時間,是我使用一個處理器的時間,乘上,程序的串行化比例,有多少程序是串行化的,F是串行程序的比重,1-F是并行程序的比重,大家可以看到,我串行程序的比例,加上并行的比例,我并行程序除以n,就是我并行所消耗的時間,加上我串行所消耗的時間,你乘以我原本一個CPU所消耗的時間,就是我n個CPU所消耗的時間,加速比呢,就是我優(yōu)化前的時候,除以我優(yōu)化后的時候,我們也可以把這個例子帶到這個公式里面去,阿姆達爾告訴我們一個什么問題呢,他就是說,增加處理器的個數(shù),并不能是我們的系統(tǒng)加速比提高,比如我們在這個地方,如果我們的n很大,如果你增加處理器的個數(shù)n很大,如果你n很大,但是如果你F很小,導(dǎo)致的結(jié)果呢,你這個數(shù)字是一個很小的數(shù)字,加速比并不會上升,那我們就合理的調(diào)整我們的F,串行化比例,和n之間的關(guān)系呢,才能夠使得加速比比較好,就是你增加CPU是沒有用個,如果你程序總體上,串行F總是接近1,下面我們來看一下古斯塔夫森定律,他是類似的

他也是說明處理器個數(shù),串行比例,加速比之間的個數(shù),他這么講的,他說,程序的執(zhí)行時間呢,可以分為兩部分,串行時間和并行時間,那程序執(zhí)行需要花多少時間呢,串行的部分,加上并行的部分,總的執(zhí)行時間呢,a加上n乘以b,n是處理器的個數(shù),那這個總時間呢,我串行執(zhí)行的時候,總的時間,a加b呢,指的就是,因此呢我的加速比呢,加速前的時間,除以加速后的時間,F是串行在程序中的比例,加速比跟CPU數(shù)量的n,看來是有一個直接的線性關(guān)系,當(dāng)我這個F很小的時候,就是串行比例很小,并行比例很高的時候,基本上加速比,CPU的數(shù)量呢,基本上成一個線性的關(guān)系,基本上強調(diào)是說,只要你能夠把這個程序,足夠的并行化,那加速比就會和你CPU成一個正比,你CPU個數(shù)越多,你加速比就越高,從這個角度說明,他們加速比的角度呢,是不同的,說明你光加CPU,是沒有用的,你必須提高串行化比例才行,總和這兩個定律呢,其實我們的結(jié)論是說,你要想讓這個程序,通過串行,通過多核,來提高你的性能,那你要做的是兩件事,第一處理好你的n,第二處理好你的F

?

超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的Java高并发程序设计前言的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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