網(wǎng)站建設(shè)運(yùn)營預(yù)算合肥seo網(wǎng)站排名
Java并發(fā)編程中的三大特性分別是原子性、可見性和有序性,它們分別靠以下機(jī)制實(shí)現(xiàn):
-
原子性:原子性指的是對(duì)于一個(gè)操作,要么全部執(zhí)行,要么全部不執(zhí)行。Java提供了一些原子性操作,例如AtomicInteger等,它們使用了底層的CAS(Compare and Swap)操作來保證操作的原子性。CAS操作是一種樂觀鎖技術(shù),當(dāng)期望值和實(shí)際值相同時(shí),才會(huì)進(jìn)行更新操作,否則會(huì)進(jìn)行重試。
-
可見性:可見性指的是當(dāng)一個(gè)線程對(duì)共享變量進(jìn)行修改后,其他線程能夠立即看到這個(gè)值的改變。Java中,可以使用volatile關(guān)鍵字來保證變量的可見性。volatile關(guān)鍵字可以保證該變量對(duì)于所有線程的可見性,即當(dāng)一個(gè)線程修改了該變量的值后,其他線程能夠立即看到這個(gè)值的改變。同時(shí),在JMM規(guī)范中,對(duì)于volatile變量的讀取操作和寫入操作會(huì)在讀操作之前插入Load with Barrier屏障,保證該操作之前的所有寫操作都已經(jīng)完成,同時(shí)在寫操作之后插入Store with Barrier屏障,保證該操作之后的所有讀操作都能看到修改后的值。這樣可以保證對(duì)于volatile變量的訪問操作具有原子性、有序性和可見性。
-
有序性:有序性指的是對(duì)于一個(gè)線程內(nèi)的操作,它們的執(zhí)行順序是按照代碼順序執(zhí)行的。在Java中,可以使用synchronized關(guān)鍵字和Lock對(duì)象等同步機(jī)制來保證線程內(nèi)的有序性。這些同步機(jī)制會(huì)保證同步代碼塊內(nèi)的代碼按照代碼順序執(zhí)行,從而保證了有序性。
總的來說,Java并發(fā)編程中的三大特性分別是原子性、可見性和有序性。原子性可以通過原子性操作和CAS操作來保證;可見性可以通過volatile關(guān)鍵字來保證;有序性可以通過同步機(jī)制(synchronized關(guān)鍵字和Lock對(duì)象)來保證。
Volitile關(guān)鍵字
在Java中,使用volatile關(guān)鍵字聲明的變量具有特殊的屬性。volatile關(guān)鍵字可以保證該變量對(duì)于所有線程的可見性,即當(dāng)一個(gè)線程修改了該變量的值后,其他線程能夠立即看到這個(gè)值的改變。volatile關(guān)鍵字可以解決多線程訪問共享變量時(shí)出現(xiàn)的線程安全問題。
在JMM規(guī)范中,對(duì)于volatile變量的讀取操作和寫入操作,會(huì)在讀操作之前插入Load with Barrier屏障,保證該操作之前的所有寫操作都已經(jīng)完成,同時(shí)在寫操作之后插入Store with Barrier屏障,保證該操作之后的所有讀操作都能看到修改后的值。這樣可以保證對(duì)于volatile變量的訪問操作具有原子性、有序性和可見性。
使用volatile關(guān)鍵字修飾的變量在修改值時(shí)不會(huì)被本地線程緩存,而是直接操作主內(nèi)存中的變量,因此能夠保證變量的可見性。同時(shí),由于volatile關(guān)鍵字可以保證變量的可見性,因此也可以保證使用該變量的操作是原子性的。
需要注意的是,volatile關(guān)鍵字只能保證對(duì)單個(gè)變量操作的原子性和可見性,并不能保證一系列操作的原子性,例如i++操作。如果需要保證多個(gè)操作的原子性,可以使用synchronized關(guān)鍵字或者Lock對(duì)象等同步機(jī)制。
總之,volatile關(guān)鍵字是Java中用于解決多線程訪問共享變量時(shí)出現(xiàn)的線程安全問題的一種手段,可以保證變量的可見性和操作的原子性。
volatile關(guān)鍵字可以保證變量對(duì)于所有線程的可見性,并且禁止指令重排序。為了實(shí)現(xiàn)這些特性,JMM在編譯器和處理器的操作之間插入了特定類型的內(nèi)存屏障,分別是:
-
Load with Barrier屏障(LoadLoad屏障):這個(gè)屏障用于保證volatile讀操作之前的所有讀操作和寫操作都已經(jīng)完成。
-
Store with Barrier屏障(StoreStore屏障):這個(gè)屏障用于保證volatile寫操作之后的所有寫操作都已經(jīng)完成。
-
Store with Load屏障(StoreLoad屏障):這個(gè)屏障用于保證volatile寫操作之后,對(duì)于volatile變量的讀操作能夠讀取到修改后的最新值。
這些內(nèi)存屏障都是通過編譯器和處理器來實(shí)現(xiàn)的,編譯器會(huì)在生成字節(jié)碼時(shí)插入相關(guān)的指令,處理器在執(zhí)行指令時(shí)會(huì)根據(jù)相關(guān)的屏障來保證指令的執(zhí)行順序和可見性。通過這些屏障,JMM保證了volatile變量的可見性、有序性和原子性。
Synchronize關(guān)鍵字
synchronized是Java中一種用于實(shí)現(xiàn)線程同步的關(guān)鍵字,其底層實(shí)現(xiàn)主要涉及到對(duì)象頭、Monitor(監(jiān)視器)和鎖升級(jí)三個(gè)方面。
-
對(duì)象頭:在Java對(duì)象頭中,有一塊用于存儲(chǔ)鎖信息的部分,包括鎖標(biāo)記、偏向線程ID、偏向時(shí)間戳等信息。synchronized關(guān)鍵字就是利用了Java對(duì)象頭中的鎖標(biāo)記來實(shí)現(xiàn)線程同步的。
-
Monitor:Monitor是一種同步機(jī)制,用于實(shí)現(xiàn)線程的互斥和協(xié)作。在Java虛擬機(jī)中,每個(gè)對(duì)象都會(huì)與一個(gè)Monitor相關(guān)聯(lián)。當(dāng)一個(gè)線程進(jìn)入synchronized代碼塊時(shí),會(huì)嘗試獲取該對(duì)象的Monitor,如果該Monitor已經(jīng)被其他線程占用,那么該線程就會(huì)被阻塞。
-
鎖升級(jí):Java中的鎖有多種狀態(tài),包括無鎖狀態(tài)、偏向鎖狀態(tài)、輕量級(jí)鎖狀態(tài)和重量級(jí)鎖狀態(tài)。synchronized關(guān)鍵字使用的是重量級(jí)鎖,但是在競爭不激烈的情況下,可以使用偏向鎖或輕量級(jí)鎖來優(yōu)化性能。偏向鎖是指在沒有競爭的情況下,將鎖標(biāo)記設(shè)置為偏向線程的ID,使得該線程可以不需要每次都去競爭鎖,提高了程序的運(yùn)行效率。輕量級(jí)鎖是指在競爭不激烈的情況下,使用CAS操作來實(shí)現(xiàn)鎖的獲取和釋放,避免了線程的上下文切換,也提高了程序的運(yùn)行效率。但是如果競爭激烈,輕量級(jí)鎖就會(huì)升級(jí)為重量級(jí)鎖,這樣就會(huì)帶來較大的性能損失。
總的來說,synchronized關(guān)鍵字的底層實(shí)現(xiàn)主要涉及到對(duì)象頭、Monitor和鎖升級(jí)三個(gè)方面。在Java虛擬機(jī)中,每個(gè)對(duì)象都會(huì)與一個(gè)Monitor相關(guān)聯(lián),當(dāng)一個(gè)線程進(jìn)入synchronized代碼塊時(shí),會(huì)嘗試獲取該對(duì)象的Monitor。synchronized關(guān)鍵字使用的是重量級(jí)鎖,但是在競爭不激烈的情況下,可以使用偏向鎖或輕量級(jí)鎖來優(yōu)化性能。