freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

java虛擬機(jī)詳解-資料下載頁(yè)

2025-06-28 08:27本頁(yè)面
  

【正文】 60。implementsRunnable{49. Accountaccount。50. intamount。51. 52. publicWithdrawThread(Accountaccount,intamount){53. =account。54. =amount。55. }56. 57. publicvoidrun(){58. for(inti=0。i100000。i++){59. (amount)。60. }61. }62. }63. }第一次執(zhí)行結(jié)果為10200,第二次執(zhí)行結(jié)果為1060,每次執(zhí)行的結(jié)果都是不確定的,因?yàn)榫€程的執(zhí)行順序是不可預(yù)見(jiàn)的。這是java同步產(chǎn)生的根源,synchronized關(guān)鍵字保證了多個(gè)線程對(duì)于同步塊是互斥的,synchronized作為一種同步手段,解決java多線程的執(zhí)行有序性和內(nèi)存可見(jiàn)性,而volatile關(guān)鍵字之解決多線程的內(nèi)存可見(jiàn)性問(wèn)題。后面將會(huì)詳細(xì)介紹。synchronized關(guān)鍵字 上面說(shuō)了,java用synchronized關(guān)鍵字做為多線程并發(fā)環(huán)境的執(zhí)行有序性的保證手段之一。當(dāng)一段代碼會(huì)修改共享變量,這一段代碼成為互斥區(qū)或臨界區(qū),為了保證共享變量的正確性,synchronized標(biāo)示了臨界區(qū)。典型的用法如下:Java代碼1. synchronized(鎖){2. 臨界區(qū)代碼3. }為了保證銀行賬戶的安全,可以操作賬戶的方法如下:Java代碼1. publicsynchronizedvoidadd(intnum){2. balance=balance+num。3. }4. publicsynchronizedvoidwithdraw(intnum){5. balance=balancenum。6. }剛才不是說(shuō)了synchronized的用法是這樣的嗎:Java代碼1. synchronized(鎖){2. 臨界區(qū)代碼3. }那么對(duì)于public synchronized void add(int num)這種情況,意味著什么呢?其實(shí)這種情況,鎖就是這個(gè)方法所在的對(duì)象。同理,如果方法是public static synchronized void add(int num),那么鎖就是這個(gè)方法所在的class。 理論上,每個(gè)對(duì)象都可以做為鎖,但一個(gè)對(duì)象做為鎖時(shí),應(yīng)該被多個(gè)線程共享,這樣才顯得有意義,在并發(fā)環(huán)境下,一個(gè)沒(méi)有共享的對(duì)象作為鎖是沒(méi)有意義的。假如有這樣的代碼:Java代碼1. publicclassThreadTest{2. publicvoidtest(){3. Objectlock=newObject()。4. synchronized(lock){5. //dosomething6. }7. }8. }lock變量作為一個(gè)鎖存在根本沒(méi)有意義,因?yàn)樗静皇枪蚕韺?duì)象,每個(gè)線程進(jìn)來(lái)都會(huì)執(zhí)行Object lock=new Object()。每個(gè)線程都有自己的lock,根本不存在鎖競(jìng)爭(zhēng)。 每個(gè)鎖對(duì)象都有兩個(gè)隊(duì)列,一個(gè)是就緒隊(duì)列,一個(gè)是阻塞隊(duì)列,就緒隊(duì)列存儲(chǔ)了將要獲得鎖的線程,阻塞隊(duì)列存儲(chǔ)了被阻塞的線程,當(dāng)一個(gè)被線程被喚醒(notify)后,才會(huì)進(jìn)入到就緒隊(duì)列,等待cpu的調(diào)度。,jvm會(huì)檢查鎖對(duì)象account的就緒隊(duì)列是否已經(jīng)有線程在等待,如果有則表明account的鎖已經(jīng)被占用了,由于是第一次運(yùn)行,account的就緒隊(duì)列為空,所以線程a獲得了鎖。如果恰好在這個(gè)時(shí)候,因?yàn)榫€程a已經(jīng)獲得了鎖還沒(méi)有釋放,所以線程b要進(jìn)入account的就緒隊(duì)列,等到得到鎖后才可以執(zhí)行。一個(gè)線程執(zhí)行臨界區(qū)代碼過(guò)程如下:1 獲得同步鎖2 清空工作內(nèi)存3 從主存拷貝變量副本到工作內(nèi)存4 對(duì)這些變量計(jì)算5 將變量從工作內(nèi)存寫(xiě)回到主存6 釋放鎖可見(jiàn),synchronized既保證了多線程的并發(fā)有序性,又保證了多線程的內(nèi)存可見(jiàn)性。生產(chǎn)者/消費(fèi)者模式 生產(chǎn)者/消費(fèi)者模式其實(shí)是一種很經(jīng)典的線程同步模型,很多時(shí)候,并不是光保證多個(gè)線程對(duì)某共享資源操作的互斥性就夠了,往往多個(gè)線程之間都是有協(xié)作的。 假設(shè)有這樣一種情況,有一個(gè)桌子,桌子上面有一個(gè)盤(pán)子,盤(pán)子里只能放一顆雞蛋,A專(zhuān)門(mén)往盤(pán)子里放雞蛋,如果盤(pán)子里有雞蛋,則一直等到盤(pán)子里沒(méi)雞蛋,B專(zhuān)門(mén)從盤(pán)子里拿雞蛋,如果盤(pán)子里沒(méi)雞蛋,則等待直到盤(pán)子里有雞蛋。其實(shí)盤(pán)子就是一個(gè)互斥區(qū),每次往盤(pán)子放雞蛋應(yīng)該都是互斥的,A的等待其實(shí)就是主動(dòng)放棄鎖,B等待時(shí)還要提醒A放雞蛋。如何讓線程主動(dòng)釋放鎖很簡(jiǎn)單,調(diào)用鎖的wait()方法就好。wait方法是從Object來(lái)的,所以任意對(duì)象都有這個(gè)方法??催@個(gè)代碼片段:Java代碼1. Objectlock=newObject()。//聲明了一個(gè)對(duì)象作為鎖2. synchronized(lock){3. balance=balancenum。4. //這里放棄了同步鎖,好不容易得到,又放棄了5. ()。6. }如果一個(gè)線程獲得了鎖lock,進(jìn)入了同步塊,(),那么這個(gè)線程會(huì)進(jìn)入到lock的阻塞隊(duì)列。()則會(huì)通知阻塞隊(duì)列的某個(gè)線程進(jìn)入就緒隊(duì)列。聲明一個(gè)盤(pán)子,只能放一個(gè)雞蛋Java代碼1. package2. publicclassPlate{3. ListObjecteggs=newArrayListObject()。4. publicsynchronizedObjectgetEgg(){5. if(()==0){6. try{7. wait()。8. }catch(InterruptedExceptione){9. }10. }11. 12. Objectegg=(0)。13. ()。//清空盤(pán)子14. notify()。//喚醒阻塞隊(duì)列的某線程到就緒隊(duì)列15. returnegg。16. }17. 18. publicsynchronizedvoidputEgg(Objectegg){19. If(()0){20. try{21. wait()。22. }catch(InterruptedExceptione){23. }24. }25. (egg)。//往盤(pán)子里放雞蛋26. notify()。//喚醒阻塞隊(duì)列的某線程到就緒隊(duì)列27. }28. }聲明一個(gè)Plate對(duì)象為plate,被線程A和線程B共享,A專(zhuān)門(mén)放雞蛋,B專(zhuān)門(mén)拿雞蛋。假設(shè)1 開(kāi)始,()為0,因此順利將雞蛋放到盤(pán)子,還執(zhí)行了notify()方法,喚醒鎖的阻塞隊(duì)列的線程,此時(shí)阻塞隊(duì)列還沒(méi)有線程。2 ,()不為0,調(diào)用wait()方法,自己進(jìn)入了鎖對(duì)象的阻塞隊(duì)列。3 此時(shí),來(lái)了一個(gè)B線程對(duì)象,()不為0,順利的拿到了一個(gè)雞蛋,還執(zhí)行了notify()方法,喚醒鎖的阻塞隊(duì)列的線程,此時(shí)阻塞隊(duì)列有一個(gè)A線程對(duì)象,喚醒后,它進(jìn)入到就緒隊(duì)列,就緒隊(duì)列也就它一個(gè),因此馬上得到鎖,開(kāi)始往盤(pán)子里放雞蛋,此時(shí)盤(pán)子是空的,因此放雞蛋成功。4 假設(shè)接著來(lái)了線程A,就重復(fù)2;假設(shè)來(lái)料線程B,就重復(fù)3。整個(gè)過(guò)程都保證了放雞蛋,拿雞蛋,放雞蛋,拿雞蛋。volatile關(guān)鍵字 volatile是java提供的一種同步手段,只不過(guò)它是輕量級(jí)的同步,為什么這么說(shuō),因?yàn)関olatile只能保證多線程的內(nèi)存可見(jiàn)性,不能保證多線程的執(zhí)行有序性。而最徹底的同步要保證有序性和可見(jiàn)性,例如synchronized。任何被volatile修飾的變量,都不拷貝副本到工作內(nèi)存,任何修改都及時(shí)寫(xiě)在主存。因此對(duì)于Valatile修飾的變量的修改,所有線程馬上就能看到,但是volatile不能保證對(duì)變量的修改是有序的。什么意思呢?假如有這樣的代碼:Java代碼1. publicclassVolatileTest{2. publicvolatileinta。3. publicvoidadd(intcount){4. a=a+count。5. }6. } 當(dāng)一個(gè)VolatileTest對(duì)象被多個(gè)線程共享,a的值不一定是正確的,因?yàn)閍=a+count包含了好幾步操作,而此時(shí)多個(gè)線程的執(zhí)行是無(wú)序的,因?yàn)闆](méi)有任何機(jī)制來(lái)保證多個(gè)線程的執(zhí)行有序性和原子性。volatile存在的意義是,任何線程對(duì)a的修改,都會(huì)馬上被其他線程讀取到,因?yàn)橹苯硬僮髦鞔?,沒(méi)有線程對(duì)工作內(nèi)存和主存的同步。所以,volatile的使用場(chǎng)景是有限的,在有限的一些情形下可以使用 volatile 變量替代鎖。要使 volatile 變量提供理想的線程安全,必須同時(shí)滿足下面兩個(gè)條件:1)對(duì)變量的寫(xiě)操作不依賴于當(dāng)前值。2)該變量沒(méi)有包含在具有其他變量的不變式中volatile只保證了可見(jiàn)性,所以Volatile適合直接賦值的場(chǎng)景,如Java代碼1. publicclassVolatileTest{2. publicvolatileinta。3. publicvoidsetA(inta){4. =a。5. }6. }在沒(méi)有volatile聲明時(shí),多線程環(huán)境下,a的最終值不一定是正確的,=a。涉及到給a賦值和將a同步回主存的步驟,這個(gè)順序可能被打亂。如果用volatile聲明了,讀取主存副本到工作內(nèi)存和同步a到主存的步驟,相當(dāng)于是一個(gè)原子操作。所以簡(jiǎn)單來(lái)說(shuō),volatile適合這種場(chǎng)景:一個(gè)變量被多個(gè)線程共享,線程直接給這個(gè)變量賦值。這是一種很簡(jiǎn)單的同步場(chǎng)景,這時(shí)候使用volatile的開(kāi)銷(xiāo)將會(huì)非常小。JVM內(nèi)存管理:深入垃圾收集器與內(nèi)存分配策略Java與C++之間有一堵由內(nèi)存動(dòng)態(tài)分配和垃圾收集技術(shù)所圍成的高墻,墻外面的人想進(jìn)去,墻里面的人卻想出來(lái)。概述:  說(shuō)起垃圾收集(Garbage Collection,下文簡(jiǎn)稱(chēng)GC),大部分人都把這項(xiàng)技術(shù)當(dāng)做Java語(yǔ)言的伴生產(chǎn)物。事實(shí)上GC的歷史遠(yuǎn)遠(yuǎn)比Java來(lái)得久遠(yuǎn),在1960年誕生于MIT的Lisp是第一門(mén)真正使用內(nèi)存動(dòng)態(tài)分配和垃圾收集技術(shù)的語(yǔ)言。當(dāng)Lisp還在胚胎時(shí)期,人們就在思考GC需要完成的3件事情:哪些內(nèi)存需要回收?什么時(shí)候回收?怎么樣回收?  經(jīng)過(guò)半個(gè)世紀(jì)的發(fā)展,目前的內(nèi)存分配策略與垃圾回收技術(shù)已經(jīng)相當(dāng)成熟,一切看起來(lái)都進(jìn)入“自動(dòng)化”的時(shí)代,那為什么我們還要去了解GC和內(nèi)存分配?答案很簡(jiǎn)單:當(dāng)需要排查各種內(nèi)存溢出、泄漏問(wèn)題時(shí),當(dāng)垃圾收集成為系統(tǒng)達(dá)到更高并發(fā)量的瓶頸時(shí),我們就需要對(duì)這些“自動(dòng)化”的技術(shù)有必要的監(jiān)控、調(diào)節(jié)手段?! “褧r(shí)間從1960年撥回現(xiàn)在,回到我們熟悉的Java語(yǔ)言。本文第一章中介紹了Java內(nèi)存運(yùn)行時(shí)區(qū)域的各個(gè)部分,其中程序計(jì)數(shù)器、VM棧、本地方法棧三個(gè)區(qū)域隨線程而生,隨線程而滅;棧中的幀隨著方法進(jìn)入、退出而有條不紊的進(jìn)行著出棧入棧操作;每一個(gè)幀中分配多少內(nèi)存基本上是在Class文件生成時(shí)就已知的(可能會(huì)由JIT動(dòng)態(tài)晚期編譯進(jìn)行一些優(yōu)化,但大體上可以認(rèn)為是編譯期可知的),因此這幾個(gè)區(qū)域的內(nèi)存分配和回收具備很高的確定性,因此在這幾個(gè)區(qū)域不需要過(guò)多考慮回收的問(wèn)題。而Java堆和方法區(qū)(包括運(yùn)行時(shí)常量池)則不一樣,我們必須等到程序?qū)嶋H運(yùn)行期間才能知道會(huì)創(chuàng)建哪些對(duì)象,這部分內(nèi)存的分配和回收都是動(dòng)態(tài)的,我們本文后續(xù)討論中的“內(nèi)存”分配與回收僅僅指這一部分內(nèi)存。對(duì)象已死?
點(diǎn)擊復(fù)制文檔內(nèi)容
范文總結(jié)相關(guān)推薦
文庫(kù)吧 www.dybbs8.com
備案圖鄂ICP備17016276號(hào)-1