www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號(hào)精選 > 小林coding
[導(dǎo)讀]Java的多線程是指程序中包含多個(gè)執(zhí)行流,即在一個(gè)程序中可以同時(shí)運(yùn)行多個(gè)不同的線程來執(zhí)行不同的任務(wù)。


0 1
起點(diǎn)



小白,坐在這間屬于華夏國超一流互聯(lián)網(wǎng)公司企鵝巴巴的小會(huì)議室里,等著技術(shù)面試官的到來。


02
突如其來的面試



Round 1


科學(xué)家路人S:

小伙子我看你簡歷上什么也沒寫,這次也是第一面,那我們就隨便問點(diǎn)簡單的多線程問題吧。先說說什么是Java的多線程吧,使用多線程有什么好處?有什么壞處?

小白

媽媽說專家的話不能信!果然,問個(gè)多線程還問好處壞處?我不想用不會(huì)用能進(jìn)企鵝巴巴么?

但是作為打工人,我認(rèn)真的回答道:

Java的多線程是指程序中包含多個(gè)執(zhí)行流,即在一個(gè)程序中可以同時(shí)運(yùn)行多個(gè)不同的線程來執(zhí)行不同的任務(wù)。

而使用多線程的好處是可以提高 CPU 的利用率。在多線程程序中,一個(gè)線程必須等待的時(shí)候,CPU 可以運(yùn)行其它的線程而不是等待,這樣就大大提高了程序的效率。也就是說允許單個(gè)程序創(chuàng)建多個(gè)并行執(zhí)行的線程來完成各自的任務(wù)。

至于多線程的壞處么,主要有三點(diǎn)。第一點(diǎn)是線程也是程序,所以線程需要占用內(nèi)存,線程越多占用內(nèi)存也越多;第二點(diǎn)是多線程需要協(xié)調(diào)和管理,所以需要 CPU 時(shí)間跟蹤線程;最后是線程之間對(duì)共享資源的訪問會(huì)相互影響,必須解決競用共享資源的問題。


Round 2


科學(xué)家路人S繼續(xù)追問:

你剛才講了“并行”這個(gè)詞,那你說說并行和并發(fā)有什么區(qū)別?

小白

并發(fā),英文單詞是concurrency,就是多個(gè)任務(wù)在同一個(gè) CPU 核上,按細(xì)分的時(shí)間片輪流(交替)執(zhí)行,從邏輯上來看那些任務(wù)是同時(shí)執(zhí)行。

并行,英文單詞是parallelism,就是單位時(shí)間內(nèi),多個(gè)處理器或多核處理器同時(shí)處理多個(gè)任務(wù),是真正意義上的“同時(shí)進(jìn)行”。

這兩句話,我相信99%的同學(xué)都知道!但是,如果想進(jìn)企鵝巴巴,如果想應(yīng)付P20的科學(xué)家!我就一定要自行的結(jié)合業(yè)務(wù)回答并發(fā)并行的優(yōu)勢!

現(xiàn)在的系統(tǒng)動(dòng)不動(dòng)就要求百萬級(jí)甚至千萬級(jí)的并發(fā)量,而多線程并發(fā)編程正是開發(fā)高并發(fā)系統(tǒng)的基礎(chǔ),利用好多線程機(jī)制可以大大提高系統(tǒng)整體的并發(fā)能力以及性能。面對(duì)復(fù)雜業(yè)務(wù)模型,并行程序會(huì)比串行程序更適應(yīng)業(yè)務(wù)需求,而并發(fā)編程更能吻合這種業(yè)務(wù)拆分 。


Round 3


路人S和路人B果然都露出了滿意的笑容。

路人B開始追問道:

那你說說看,在操作系統(tǒng)中用戶級(jí)線程和內(nèi)核級(jí)線程是什么?這兩個(gè)線程在多核CPU的計(jì)算機(jī)上是否都能并行?

小白

在操作系統(tǒng)的設(shè)計(jì)中,為了防止用戶操作敏感指令而對(duì)OS帶來安全隱患,我們把OS分成了用戶空間(user space)和內(nèi)核空間(kernel space)。

通過用戶空間的庫類實(shí)現(xiàn)的線程,就是用戶級(jí)線程(user-level threads,ULT)。這種線程不依賴于操作系統(tǒng)核心,進(jìn)程利用線程庫提供創(chuàng)建、同步、調(diào)度和管理線程的函數(shù)來控制用戶線程。

說著,我拿了一支筆,畫了這么一張圖:

在圖里,我們可以清楚的看到,線程表(管理線程的數(shù)據(jù)結(jié)構(gòu))是處于進(jìn)程內(nèi)部的,完全處于用戶空間層面,內(nèi)核空間對(duì)此一無所知!當(dāng)然,用戶線程也可以沒有線程表!

相應(yīng)的,由OS內(nèi)核空間直接掌控的線程,稱為內(nèi)核級(jí)線程(kernel-level threads,KLT)。其依賴于操作系統(tǒng)核心,由內(nèi)核的內(nèi)部需求進(jìn)行創(chuàng)建和撤銷。

接著,我畫下了這張圖:

同樣的,在圖中,我們看到內(nèi)核線程的線程表(thread table)位于內(nèi)核中,包括了線程控制塊(TCB),一旦線程阻塞,內(nèi)核會(huì)從當(dāng)前或者其他進(jìn)程(process)中重新選擇一個(gè)線程保證程序的執(zhí)行。

對(duì)于用戶級(jí)線程來說,其線程的切換發(fā)生在用戶空間,這樣的線程切換至少比陷入內(nèi)核要快一個(gè)數(shù)量級(jí)。但是該種線程有個(gè)嚴(yán)重的缺點(diǎn):如果一個(gè)線程開始運(yùn)行,那么該進(jìn)程中其他線程就不能運(yùn)行,除非第一個(gè)線程自動(dòng)放棄CPU。因?yàn)樵谝粋€(gè)單獨(dú)的進(jìn)程內(nèi)部,沒有時(shí)鐘中斷,所以不能用輪轉(zhuǎn)調(diào)度(輪流)的方式調(diào)度線程。

也就是說,同一進(jìn)程中的用戶級(jí)線程,在不考慮調(diào)起多個(gè)內(nèi)核級(jí)線程的基礎(chǔ)上,是沒有辦法利用多核CPU的,其實(shí)質(zhì)是并發(fā)而非并行

對(duì)于內(nèi)核級(jí)線程來說,其線程在內(nèi)核中創(chuàng)建和撤銷線程的開銷比較大,需要考慮上下文切換的開銷。

但是,內(nèi)核級(jí)線程是可以利用多核CPU的,即可以并行

這回答的累死我了,不過為了能進(jìn)企鵝巴巴,走向人生巔峰,一切都值了!


Round 4


路人B點(diǎn)了點(diǎn)頭說:

嗯,小伙子基礎(chǔ)還是比較牢靠的!那你說說Java里的多線程是用戶級(jí)線程還是內(nèi)核級(jí)線程呢?

小白

是...當(dāng)我要脫口而出的時(shí)候,發(fā)現(xiàn)不對(duì),這面試官在套路我!堂堂科學(xué)家,套路還沒入職的孩子么?

Java里的多線程,既不是用戶級(jí)線程,也不是內(nèi)核級(jí)線程!

首先,Java是跨操作平臺(tái)的語言,是使用JVM去運(yùn)行編譯文件的。不同的JVM對(duì)線程的實(shí)現(xiàn)不同,相同的JVM對(duì)不同操作平臺(tái)的線程實(shí)現(xiàn)方式也有區(qū)別!

其次,要講明白程序級(jí)別實(shí)現(xiàn)多線程,就必須先說一下多線程模型。

裂開!怎么感覺這又是一道大題?。是操作系統(tǒng)的科學(xué)家吧!感覺問的都是很底層的東西了啊,現(xiàn)在程序員內(nèi)卷成這樣了么?實(shí)習(xí)生都問這么底層的問題了?雖然百般不爽,但是為了拿下美女HR,不!是橫掃offer。我要給路人B講明白這個(gè)線程模型!

上面我說過OS上的線程分為ULT和KLT,我們寫程序的代碼只能是在用戶空間里寫代碼!而程序運(yùn)行中,基本上都會(huì)進(jìn)入內(nèi)核運(yùn)行,所以我們?cè)趯?shí)現(xiàn)程序級(jí)別多線程的時(shí)候,必須讓ULT映射到KLT上去。在程序級(jí)別的多線程設(shè)計(jì)里,有以下三種多線程模型。

多對(duì)1模型:在多對(duì)一模型中,多個(gè)ULT映射到1個(gè)KLT上去,此時(shí)ULT的進(jìn)程表處于進(jìn)程之中。

1對(duì)1模型:在一對(duì)一模型中,1個(gè)ULT對(duì)應(yīng)1個(gè)KLT。自己不在進(jìn)程中創(chuàng)建線程表來管理,幾行代碼之后直接通過系統(tǒng)調(diào)用調(diào)起KLT就能實(shí)現(xiàn)。

多對(duì)多模型:在多對(duì)多模型中,N個(gè)ULT對(duì)應(yīng)小于等于N個(gè)的KLT。這種模型結(jié)合了1對(duì)1和多對(duì)1的優(yōu)點(diǎn),用戶創(chuàng)建線程沒有限制,阻塞內(nèi)核系統(tǒng)的命令不會(huì)阻塞整個(gè)進(jìn)程。

最后,就拿最熱門的HotSpot VM來說吧,他在Solaris上就有兩種線程實(shí)現(xiàn)方式,可以讓用戶選擇一對(duì)一或多對(duì)多這兩種模型;而在Windows和Linux下,使用的都是一對(duì)一的多線程模型,Java的線程通過一一映射到Light Weight Process(輕量級(jí)進(jìn)程,LWP)從而實(shí)現(xiàn)了和KLT的一一對(duì)應(yīng)。


Round 5


路人B聽到這個(gè)回答,眼睛都亮了!直接追問道:

ULT如何映射到KLT?怎么調(diào)起的?

小白

ULT在執(zhí)行的過程中,如果執(zhí)行的指令需要進(jìn)入內(nèi)核態(tài),則ULT會(huì)通過系統(tǒng)調(diào)用調(diào)起一個(gè)KLT!

所謂系統(tǒng)調(diào)度,就是在OS中分割用戶空間和內(nèi)核空間的API。


Round 6


路人B繼續(xù)追問道:

ULT的執(zhí)行過程中可以不調(diào)起KLT么?舉個(gè)例子。

小白

可以不調(diào)起,比如ULT中就只有sleep這個(gè)指令,就不會(huì)進(jìn)入內(nèi)核態(tài)執(zhí)行,更不會(huì)調(diào)起KLT。

問到這里,我有點(diǎn)吐血了都!看著B對(duì)我的回答很滿意,我心中卻把B已經(jīng)問候了一百遍!


Round 7


路人S總算接過了話題:

看來同學(xué)對(duì)于底層的知識(shí)理解還湊合,那你有沒有看過HotSpot的源碼?能不能簡單說說看Java的線程是怎么運(yùn)行的?

小白

這問的還上癮了?P20的問題咋這么“簡單”呢!說實(shí)話,自從前幾天發(fā)生了靈異事件之后,我確實(shí)技術(shù)突飛猛進(jìn),這個(gè)源代碼我好像還真的瞄了一眼,不過我不能暴露自己擁有金手指的秘密??!

于是我撓了撓頭,思考了1分鐘,然后說道:

源碼以前看過,只能記得一個(gè)大概。

1、在Java中,使用java.lang.Thread的構(gòu)造方法來構(gòu)建一個(gè)java.lang.Thread對(duì)象,此時(shí)只是對(duì)這個(gè)對(duì)象的部分字段(例如線程名,優(yōu)先級(jí)等)進(jìn)行初始化;

2、調(diào)用java.lang.Thread對(duì)象的start()方法,開始此線程。此時(shí),在start()方法內(nèi)部,調(diào)用start0() 本地方法來開始此線程;

3、start0()在VM中對(duì)應(yīng)的是JVM_StartThread,也就是,在VM中,實(shí)際運(yùn)行的是JVM_StartThread方法(宏),在這個(gè)方法中,創(chuàng)建了一個(gè)JavaThread對(duì)象;

4、在JavaThread對(duì)象的創(chuàng)建過程中,會(huì)根據(jù)運(yùn)行平臺(tái)創(chuàng)建一個(gè)對(duì)應(yīng)的OSThread對(duì)象,且JavaThread保持這個(gè)OSThread對(duì)象的引用;

5、在OSThread對(duì)象的創(chuàng)建過程中,創(chuàng)建一個(gè)平臺(tái)相關(guān)的底層級(jí)線程,如果這個(gè)底層級(jí)線程失敗,那么就拋出異常;

6、在正常情況下,這個(gè)底層級(jí)的線程開始運(yùn)行,并執(zhí)行java.lang.Thread對(duì)象的run方法;

7、當(dāng)java.lang.Thread生成的Object的run()方法執(zhí)行完畢返回后,或者拋出異常終止后,終止native thread;

8、最后就是釋放相關(guān)的資源(包括內(nèi)存、鎖等)

大概就是以上這么個(gè)步驟吧。

回答完這個(gè),我要跪謝我的金手指了!我看見路人S在電腦上敲著什么,估計(jì)他也比較懵,沒想到我居然能答得上來吧!


Round 8


路人S 對(duì)此不置可否,說道:

那你說說什么是上下文切換吧。

小白

多線程編程中一般線程的個(gè)數(shù)都大于 CPU 核心的個(gè)數(shù),而一個(gè) CPU 核心在任意時(shí)刻只能被一個(gè)線程使用,為了讓這些線程都能得到有效執(zhí)行,CPU 采取的策略是為每個(gè)線程分配時(shí)間片并輪轉(zhuǎn)的形式。

時(shí)間片是CPU分配給各個(gè)線程的時(shí)間,因?yàn)闀r(shí)間非常短,所以CPU不斷通過切換線程,讓我們覺得多個(gè)線程是同時(shí)執(zhí)行的,時(shí)間片一般是幾十毫秒。

當(dāng)一個(gè)線程的時(shí)間片用完的時(shí)候就會(huì)重新處于就緒狀態(tài)讓給其他線程使用,這個(gè)過程就屬于一次上下文切換。

概括來說就是:當(dāng)前任務(wù)在執(zhí)行完 CPU 時(shí)間片切換到另一個(gè)任務(wù)之前會(huì)先保存自己的狀態(tài),以便下次再切換回這個(gè)任務(wù)時(shí),可以再加載這個(gè)任務(wù)的狀態(tài)。任務(wù)從保存到再加載的過程就是一次上下文切換。


Round 9


路人S繼續(xù)問道:

頻繁切換上下文會(huì)有什么問題?

小白

上下文切換通常是計(jì)算密集型的,每次切換時(shí),需要保存當(dāng)前的狀態(tài)起來,以便能夠進(jìn)行恢復(fù)先前狀態(tài),而這個(gè)切換時(shí)非常損耗性能。

也就是說,它需要相當(dāng)可觀的處理器時(shí)間,在每秒幾十上百次的切換中,每次切換都需要納秒量級(jí)的時(shí)間。所以,上下文切換對(duì)系統(tǒng)來說意味著消耗大量的 CPU 時(shí)間,事實(shí)上,可能是操作系統(tǒng)中時(shí)間消耗最大的操作。

Linux 相比與其他操作系統(tǒng)(包括其他類 Unix 系統(tǒng))有很多的優(yōu)點(diǎn),其中有一項(xiàng)就是,其上下文切換和模式切換的時(shí)間消耗非常少。


Round 10


S繼續(xù)問:

減少上下文切換的方式有哪些?

小白

通常減少上下文切換的方式有:

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

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

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

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


Round 11


路人B聽了,眼睛一亮,立刻追問道:

協(xié)程是什么?和用戶線程有什么區(qū)別?

小白

我聽了真想抽自己幾個(gè)嘴巴子,怎么又來了!B是只會(huì)OS吧!

協(xié)程的英文單詞是Coroutine,這是一個(gè)程序組件,它既不是線程也不是進(jìn)程。它的執(zhí)行過程更類似于一個(gè)方法,或者說不帶返回值的函數(shù)調(diào)用。

我看到過stack overflow和很多博客里,都認(rèn)為這兩者是一個(gè)東西。但是,在我的理解中,這兩者還是有區(qū)別的。

不可否認(rèn)的是,協(xié)程和ULT做的是同一個(gè)事情。所以從某種角度上講,他們確實(shí)是等價(jià)的!

但是,ULT這個(gè)概念被提出的時(shí)候,其背后的思想本質(zhì)是講ULT是個(gè)本機(jī)線程,也就是使用了OS的用戶空間內(nèi)提供的庫類直接創(chuàng)建的線程。這個(gè)時(shí)候,你不需要在OS上面添加一些其他第三方的庫類。

而協(xié)程這個(gè)概念是康威定律的提出者M(jìn)elvin Edward Conway在1958年提出的一個(gè)概念,其背后的思想是不直接使用OS本身的庫類,自己做一些庫類去實(shí)現(xiàn)并發(fā)。在那個(gè)年代,OS上面的第三方庫類并不像現(xiàn)在這么流行,OS本身的庫類和其他第三方庫類的結(jié)合也并不像今天這么容易。所以協(xié)程并不是本機(jī)線程,他是需要借助一些其他不屬于OS的第三方庫類調(diào)用OS用戶空間的庫類來實(shí)現(xiàn)達(dá)到ULT的效果。

當(dāng)然,這個(gè)概念在今天來看,就會(huì)顯得很讓人混淆了。因?yàn)榈降啄男祛愃闶荗S本機(jī)的庫類,哪些算是第三方庫類?這和1960年的時(shí)候已經(jīng)有絕大的區(qū)別了!所以大家認(rèn)為這兩者是一個(gè)東西,其實(shí)也不能說他說的不對(duì),只能說可能對(duì)這個(gè)思想本身背后代表的東西不明白。


Round 12


路人B聽了,立刻坐直了身體,繼續(xù)追問道:

那你知道fiber么?這個(gè)和上面兩個(gè)名詞有什么區(qū)別?

小白

fiber也是一種本機(jī)線程,其本質(zhì)是一種特殊的ULT,即更輕量級(jí)的ULT。說白了就是這種ULT的線程表一定存于進(jìn)程之中

而我們?cè)跇?gòu)建一對(duì)一多線程模型的時(shí)候,ULT的線程表其實(shí)還是交給內(nèi)核了!這是兩者之間最直接的差別。所以我們經(jīng)常稱fiber就是協(xié)同調(diào)度的ULT,在win32中可以調(diào)用fiber來構(gòu)建多對(duì)多的多線程模型。

其實(shí),fiber、coroutine和ULT在用戶層面能看到的效果是基本等價(jià)的。

其中ULT是描述OS庫本身提供的功能;fiber描述的是OS提供的協(xié)同調(diào)度的ULT;coroutine描述的是第三方實(shí)現(xiàn)的并發(fā)并行功能。

這些名詞很多都是歷史原因的問題,同時(shí)也是深入研究需要了解的事情,我們普通程序員在使用的時(shí)候,更多的關(guān)心的是應(yīng)用層方面的東西。而這些名詞的理解已經(jīng)深入到源碼層了。


Round 13


路人S估計(jì)被我秀的腦殼痛了,立刻說道:

還是講講看在 Java 程序中怎么保證多線程的運(yùn)行安全吧。

小白

Java的線程安全在三個(gè)方面體現(xiàn):

原子性:提供互斥訪問,同一時(shí)刻只能有一個(gè)線程對(duì)數(shù)據(jù)進(jìn)行操作,在Java中使用了atomic和synchronized這兩個(gè)關(guān)鍵字來確保原子性;

可見性:一個(gè)線程對(duì)主內(nèi)存的修改可以及時(shí)地被其他線程看到,在Java中使用了synchronized和volatile這兩個(gè)關(guān)鍵字確保可見性;

有序性:一個(gè)線程觀察其他線程中的指令執(zhí)行順序,由于指令重排序,該觀察結(jié)果一般雜亂無序,在Java中使用了happens-before原則來確保有序性。


Round 14


路人S 繼續(xù)問道:

你剛才講了有序性,那你說說代碼為什么會(huì)重排序?

小白

在執(zhí)行程序時(shí),為了提高性能,處理器和編譯器常常會(huì)對(duì)指令進(jìn)行重排序。


Round 15


路人S繼續(xù)追問:

重排序是想怎么重排就重排么?

小白

這面試官也很難纏啊,怎么一直在追問,是需要我給他孝敬一根華子么?要不是看著旁邊有個(gè)美女HR,我早就孝敬S他老人家了!

當(dāng)然不是!不能隨意重排序,不是你想怎么排序就怎么排序,它需要滿足以下兩個(gè)條件:

1、在單線程環(huán)境下不能改變程序運(yùn)行的結(jié)果;

2、存在數(shù)據(jù)依賴關(guān)系的不允許重排序。

所以重排序不會(huì)對(duì)單線程有影響,只會(huì)破壞多線程的執(zhí)行語義。


Round 16


路人S繼續(xù)追問道:

那你講講看在Java中如何保障重排序不影響單線程的吧。

小白

保障這一結(jié)果是因?yàn)樵诰幾g器,runtime 和處理器都必須遵守as-if-serial語義規(guī)則。

為了遵守as-if-serial語義,編譯器和處理器不會(huì)對(duì)存在數(shù)據(jù)依賴關(guān)系的操作做重排序,因?yàn)檫@種重排序會(huì)改變執(zhí)行結(jié)果。但是,如果操作之間不存在數(shù)據(jù)依賴關(guān)系,這些操作可能被編譯器和處理器重排序。

我來舉個(gè)例子吧

說著我拿著筆在紙上寫了三行簡單的代碼:

我們看這個(gè)例子,A和C之間存在數(shù)據(jù)依賴關(guān)系,同時(shí)B和C之間也存在數(shù)據(jù)依賴關(guān)系。因此在最終執(zhí)行的指令序列中,C不能被重排序到A和B的前面,如果C排到A和B的前面,那么程序的結(jié)果將會(huì)被改變。但A和B之間沒有數(shù)據(jù)依賴關(guān)系,編譯器和處理器可以重排序A和B之間的執(zhí)行順序。

這就是as-if-serial語義。


Round 17


路人S繼續(xù)問道:

那你說說看你剛才講的happens-before原則吧。

小白

happens-before說白了就是誰在誰前面發(fā)生的一個(gè)關(guān)系。

HB規(guī)則是Java內(nèi)存模型(JMM)向程序員提供的跨線程內(nèi)存可見性保證。

說的直白一點(diǎn),就是如果A線程的寫操作a與B線程的讀操作b之間存在happens-before關(guān)系,盡管a操作和b操作在不同的線程中執(zhí)行,但JMM向程序員保證a操作將對(duì)b操作可見。

具體的定義為:

1、如果一個(gè)操作happens-before另一個(gè)操作,那么第一個(gè)操作的執(zhí)行結(jié)果將對(duì)第二個(gè)操作可見,而且第一個(gè)操作的執(zhí)行順序排在第二個(gè)操作之前。

2、兩個(gè)操作之間存在happens-before關(guān)系,并不意味著Java平臺(tái)的具體實(shí)現(xiàn)必須要按照happens-before關(guān)系指定的順序來執(zhí)行。如果重排序之后的執(zhí)行結(jié)果,與按happens-before關(guān)系來執(zhí)行的結(jié)果一致,那么這種重排序并不非法。

具體的規(guī)則有8條:

1、程序順序規(guī)則:一個(gè)線程中的每個(gè)操作,happens-before于該線程中的任意后續(xù)操作。

2、監(jiān)視器鎖規(guī)則:對(duì)一個(gè)鎖的解鎖,happens-before于隨后對(duì)這個(gè)鎖的加鎖。

3、volatile變量規(guī)則:對(duì)一個(gè)volatile域的寫,happens-before于任意后續(xù)對(duì)這個(gè)volatile域的讀。

4、傳遞性:如果A happens-before B,且B happens-before C,那么A happens-before C。

5、start()規(guī)則:如果線程A執(zhí)行操作ThreadB.start()(啟動(dòng)線程B),那么A線程的ThreadB.start()操作happens-before于線程B中的任意操作。

6、Join()規(guī)則:如果線程A執(zhí)行操作ThreadB.join()并成功返回,那么線程B中的任意操作happens-before于線程A從ThreadB.join()操作成功返回。

7、程序中斷規(guī)則:對(duì)線程interrupted()方法的調(diào)用先行于被中斷線程的代碼檢測到中斷時(shí)間的發(fā)生。

8、對(duì)象finalize規(guī)則:一個(gè)對(duì)象的初始化完成(構(gòu)造函數(shù)執(zhí)行結(jié)束)先行于發(fā)生它的finalize()方法的開始。


Round 18


路人S接著追問:

你剛才說HB規(guī)則不代表最終的執(zhí)行順序,能不能舉個(gè)例子。

小白

就拿講as-if-serial提到的例子舉例吧,例子很簡單就是面積=寬*高。

利用HB的程序順序規(guī)則,存在三個(gè)happens-before關(guān)系:

1、A happens-before B;

2、B happens-before C;

3、A happens-before C。

這里的第三個(gè)關(guān)系是利用傳遞性進(jìn)行推論的。這里的第三個(gè)關(guān)系是利用傳遞性進(jìn)行推論的。

A happens-before B,定義1要求A執(zhí)行結(jié)果對(duì)B可見,并且A操作的執(zhí)行順序在B操作之前;但與此同時(shí)利用HB定義中的第二條,A、B操作彼此不存在數(shù)據(jù)依賴性,兩個(gè)操作的執(zhí)行順序?qū)ψ罱K結(jié)果都不會(huì)產(chǎn)生影響。

在不改變最終結(jié)果的前提下,允許A,B兩個(gè)操作重排序,即happens-before關(guān)系并不代表了最終的執(zhí)行順序。




哈嘍,我是小林,就愛圖解計(jì)算機(jī)基礎(chǔ),如果覺得文章對(duì)你有幫助,歡迎分享給你的朋友,也給小林點(diǎn)個(gè)「在看」,這對(duì)小林非常重要,謝謝你們,給各位小姐姐小哥哥們抱拳了,我們下次見!


推薦閱讀

你不好奇 Linux 是如何收發(fā)網(wǎng)絡(luò)包的?

小小的 float,藏著大大的學(xué)問

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場,如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉