亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

【實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計5】讓普通變量也享受原子操作

appetizerio / 2363人閱讀

摘要:有時候,由于初期考慮不周,或者后期的需求變化,一些普通變量可能也會有線程安全的需求。它可以讓你在不改動或者極少改動原有代碼的基礎(chǔ)上,讓普通的變量也享受操作帶來的線程安全性,這樣你可以修改極少的代碼,來獲得線程安全的保證。

有時候,由于初期考慮不周,或者后期的需求變化,一些普通變量可能也會有線程安全的需求。如果改動不大,我們可以簡單地修改程序中每一個使用或者讀取這個變量的地方。但顯然,這樣并不符合軟件設(shè)計中的一條重要原則——開閉原則。也就是系統(tǒng)對功能的增加應(yīng)該是開發(fā)的,而對修改應(yīng)該是相對保守的。而且,如果系統(tǒng)里使用到這個變量的地方特別多,一個一個修改也是一件令人厭煩的事情(況且很多使用場景下可能只是只讀的,并無線程安全的強(qiáng)烈要求,完全可以保持原樣)。

如果你有這種困擾,在這里根本不需要擔(dān)心,因?yàn)樵谠影镞€有一個實(shí)用的工具類AtomicIntegerFieldUpdater。它可以讓你在不改動(或者極少改動)原有代碼的基礎(chǔ)上,讓普通的變量也享受CAS操作帶來的線程安全性,這樣你可以修改極少的代碼,來獲得線程安全的保證。這聽起來是不是讓人很激動呢?

根據(jù)數(shù)據(jù)類型不同,這個Updater有3種,分別是AtomicIntegerFieldUpdater、AtomicLongFieldUpdater和AtomicReferenceFieldUpdater。顧名思義,它們分別可以對int、long和普通對象就行CAS修改。

現(xiàn)在來思考這么一個場景。假設(shè)某地要進(jìn)行一次選舉?,F(xiàn)在模擬這個機(jī)票場景,如果選民投了候選人一票,就記為1,否則記為0。最終的選票顯然就是所有數(shù)據(jù)的簡單求和。

01 public class AtomicIntegerFieldUpdaterDemo {
02     public static class Candidate{
03         int id;
04         volatile int score;
05     }
06     public final static AtomicIntegerFieldUpdater scoreUpdater 
07         = AtomicIntegerFieldUpdater.newUpdater(Candidate.class, "score");
08     //檢查Updater是否工作正確
09     public static AtomicInteger allScore=new AtomicInteger(0);
10     public static void main(String[] args) throws InterruptedException {
11         final Candidate stu=new Candidate();
12         Thread[] t=new Thread[10000];
13         for(int i = 0 ; i < 10000 ; i++) {  
14             t[i]=new Thread() {  
15                 public void run() {  
16                     if(Math.random()>0.4){
17                         scoreUpdater.incrementAndGet(stu);
18                         allScore.incrementAndGet();
19                     }
20                 }  
21             };
22             t[i].start();
23         }  
24         for(int i = 0 ; i < 10000 ; i++) {  t[i].join();}
25         System.out.println("score="+stu.score);
26         System.out.println("allScore="+allScore);
27     }
28 }
 

上述代碼模擬了這個計票場景。候選人的得票數(shù)量記錄在Candidate.score中。注意,它是一個普通的volatile變量。而volatile變量并不是線程安全的。第6~7行定義了

AtomicIntegerFieldUpdater實(shí)例,用來對Candidate.score進(jìn)行寫入。而后續(xù)的allScore我們用來檢查AtomicIntegerFieldUpdater的正確性。如果AtomicIntegerFieldUpdater真的保證了線程安全,那么最終Candidate.score和allScore的值必然是相等的。否則,就說明AtomicIntegerFieldUpdater根本沒有確保線程安全的寫入。第12~21行模擬了計票過程,這里假設(shè)有大約60%的人投贊成票,并且投票是隨機(jī)進(jìn)行的。第17行使用Updater修改Candidate.score(這里應(yīng)該是線程安全的),第18行使用AtomicInteger計數(shù),作為參考基準(zhǔn)。

大家如果運(yùn)行這段程序,不難發(fā)現(xiàn),最終的Candidate.score總是和allScore絕對相等。這說明AtomicIntegerFieldUpdater很好地保證了Candidate.score的線程安全。

雖然AtomicIntegerFieldUpdater很好用,但是還是有幾個注意事項(xiàng):

第一,Updater只能修改它可見范圍內(nèi)的變量。因?yàn)閁pdater使用反射得到這個變量。如果變量不可見,就會出錯。比如如果score申明為private,就是不可行的。

第二,為了確保變量被正確的讀取,它必須是volatile類型的。如果我們原有代碼中未申明這個類型,那么簡單得申明一下就行,這不會引起什么問題。

第三,由于CAS操作會通過對象實(shí)例中的偏移量直接進(jìn)行賦值,因此,它不支持static字段(Unsafe. objectFieldOffset()不支持靜態(tài)變量)。

好了,通過AtomicIntegerFieldUpdater,是不是讓我們可以更加隨心所欲得對系統(tǒng)關(guān)鍵數(shù)據(jù)進(jìn)行線程安全地保護(hù)呢?

【實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計1】Java中的指針:Unsafe類
【實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計2】無鎖的對象引用:AtomicReference
【實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計 3】帶有時間戳的對象引用:AtomicStampedReference
【實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計 4】數(shù)組也能無鎖AtomicIntegerArray

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/65622.html

相關(guān)文章

  • 實(shí)戰(zhàn)Java并發(fā)程序設(shè)計6】挑戰(zhàn)無鎖算法

    摘要:在本例中,講述的無鎖來自于并發(fā)包我們將這個無鎖的稱為。在這里,我們使用二維數(shù)組來表示的內(nèi)部存儲,如下變量存放所有的內(nèi)部元素。為什么使用二維數(shù)組去實(shí)現(xiàn)一個一維的呢這是為了將來進(jìn)行動態(tài)擴(kuò)展時可以更加方便。 我們已經(jīng)比較完整得介紹了有關(guān)無鎖的概念和使用方法。相對于有鎖的方法,使用無鎖的方式編程更加考驗(yàn)一個程序員的耐心和智力。但是,無鎖帶來的好處也是顯而易見的,第一,在高并發(fā)的情況下,它比有鎖...

    zengdongbao 評論0 收藏0
  • 并發(fā) - 基礎(chǔ)

    摘要:異步非阻塞方式,任務(wù)的完成的通知由其他線程發(fā)出。并發(fā)并行死鎖饑餓活鎖死鎖線程持有,線程持有。如等,在多線程情況下,該操作不是原子級別的而是原子的,所以一般用于狀態(tài)標(biāo)記。 同步/異步、阻塞/非阻塞 同步/異步是 API 被調(diào)用者的通知方式。阻塞/非阻塞則是 API 調(diào)用者的等待方式(線程掛機(jī)/不掛起)。 同步非阻塞 Future方式,任務(wù)的完成要主線程自己判斷。如NIO,后臺有多個任務(wù)在...

    phpmatt 評論0 收藏0
  • java-實(shí)戰(zhàn)java并發(fā)程序設(shè)計-ch1走入并行的世界

    摘要:參考何去何從的并行計算忘記該死的并行并行程序的復(fù)雜性和亂序性,并行程序設(shè)計十分復(fù)雜??膳碌默F(xiàn)實(shí)摩爾定律的失效單核上的晶體管數(shù)目達(dá)到極限。并發(fā)級別阻塞重入鎖無饑餓兩個線程優(yōu)先級不同,低優(yōu)先級的可能產(chǎn)生饑餓。 Chapter1 參考:https://github.com/chengbingh... 1.1何去何從的并行計算 1.1.1 忘記該死的并行并行程序的復(fù)雜性和亂序性,并行程序設(shè)計十...

    suxier 評論0 收藏0
  • 實(shí)戰(zhàn)java并發(fā)程序設(shè)計第一章

    摘要:通過指令重排可以減少流水線停頓提升巨大效率原則程序順序原則一個線程內(nèi)保證語義的串行性。鎖規(guī)則解鎖必然發(fā)生在隨后的加鎖前。線程的方法先于它的每一個動作。 1. 基本概念 同步(Synchronous)和異步(Asynchronous) 并發(fā)(Conncurrency)和并行(Parallelism) 臨界區(qū) 阻塞(Blocking)與非阻塞(Non-Blocking) 死鎖(Deadl...

    moven_j 評論0 收藏0
  • 實(shí)戰(zhàn)Java并發(fā)程序設(shè)計 4】數(shù)組能無鎖AtomicIntegerArray

    摘要:當(dāng)前可用的原子數(shù)組有和,分別表示整數(shù)數(shù)組型數(shù)組和普通的對象數(shù)組。摘自實(shí)戰(zhàn)高并發(fā)程序設(shè)計一書實(shí)戰(zhàn)高并發(fā)程序設(shè)計中的指針類實(shí)戰(zhàn)高并發(fā)程序設(shè)計無鎖的對象引用實(shí)戰(zhàn)高并發(fā)程序設(shè)計帶有時間戳的對象引用 除了提供基本數(shù)據(jù)類型外,JDK還為我們準(zhǔn)備了數(shù)組等復(fù)合結(jié)構(gòu)。當(dāng)前可用的原子數(shù)組有:AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray,分別...

    zlyBear 評論0 收藏0

發(fā)表評論

0條評論

appetizerio

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<