資源描述:
《java厲善信息-多線程-并發(fā)編程講解》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在工程資料-天天文庫。
1、Java多線程并發(fā)編程一、多線程1、操作系統(tǒng)有兩個(gè)容易混淆的概念,進(jìn)程和線程。進(jìn)程:一個(gè)計(jì)算機(jī)程序的運(yùn)行實(shí)例,包含了需要執(zhí)行的指令;有自己的獨(dú)立地址空間,包含程序內(nèi)容和數(shù)據(jù);不同進(jìn)程的地址空間是互相隔離的;進(jìn)程擁有各種資源和狀態(tài)信息,包括打開的文件、子進(jìn)程和信號(hào)處理。線程:表示程序的執(zhí)行流程,是CPU調(diào)度執(zhí)行的基本單位;線程有自己的程序H?數(shù)器、寄存器、堆棧和幀。同一進(jìn)程屮的線程共川相同的地址空間,同時(shí)共享進(jìn)進(jìn)程鎖擁有的內(nèi)存和其他資源。2、Java標(biāo)準(zhǔn)庫提供了進(jìn)程和線程相關(guān)的API,進(jìn)程主要包括表示進(jìn)程的java.
2、lang.Process類和創(chuàng)建進(jìn)程的java.Iang.ProcessBuilder類;表示線程的是java.Iang.Thread類,在虛擬機(jī)啟動(dòng)之G,通常只有Java類的main方法這個(gè)普通線程運(yùn)行,運(yùn)行時(shí)可以創(chuàng)建和啟動(dòng)新的線程;還有一類守護(hù)線程(damonthread),守護(hù)線程在后臺(tái)運(yùn)行,提供程序運(yùn)行時(shí)所需的服務(wù)。當(dāng)虛擬機(jī)中運(yùn)行的所有線程都是守護(hù)線程時(shí),虛擬機(jī)終止運(yùn)行。3、線程間的可見性:一個(gè)線程對(duì)進(jìn)程中共享的數(shù)據(jù)的修改,是否對(duì)另一個(gè)線程可見可見性問題:a、CPU采用時(shí)間片輪轉(zhuǎn)等不同算法來對(duì)線程進(jìn)行調(diào)度p
3、ublicclassIdGenerator{privateintvalue=0;publicintgetNext(){returnveilue++;對(duì)于IdGenerator的getNextO方法,在多線程下不能保證返回值是不重復(fù)的:各個(gè)線程之間相互競(jìng)爭(zhēng)CPU吋間來獲取運(yùn)行機(jī)會(huì),CPU切換可能發(fā)生在執(zhí)行間隙。以上代碼getNext()的指令序列:CPU切換可能發(fā)生在7條指令之間,多個(gè)getNext的指令交織在一起。1aload_02dup3getfield#124dupxl5iconstl6iadd7putfiel
4、d#12b、CPU緩存:R前CPU—般采用層次結(jié)構(gòu)的多級(jí)緩存的架構(gòu),有的CPU提供了L1、L2和L3三級(jí)緩存。當(dāng)CPU需要讀取主存屮某個(gè)位賈的數(shù)據(jù)時(shí),會(huì)一次檢查各級(jí)緩存巾是否存在對(duì)應(yīng)的數(shù)裾。如果有,直接從緩存屮讀取,這比從主存中讀取速度快很多。當(dāng)CPU需要寫入時(shí),數(shù)據(jù)先被寫入緩存中,之后再某個(gè)吋間點(diǎn)寫回主存。所以某些時(shí)間點(diǎn)上,緩存中的數(shù)據(jù)與主存中的數(shù)據(jù)可能是不一致。c、指令順序重排出行性能考慮,編譯器在編譯時(shí)可能會(huì)對(duì)字節(jié)代碼的指令順序進(jìn)行重新排列,以優(yōu)化指令的執(zhí)行順序,在單線程中不會(huì)有問題,但在多線程可能產(chǎn)生與可見
5、性相關(guān)的問題。二、Java內(nèi)存模型(JavaMemoryModel)屏蔽了CPU緩存等細(xì)節(jié),只關(guān)注主存中的共享變量;關(guān)注對(duì)象的實(shí)例域、靜態(tài)域和數(shù)組元素;關(guān)注線程間的動(dòng)作。1、volatile關(guān)鍵詞:用來對(duì)共享變量的訪問進(jìn)行同步,上一次寫入操作的結(jié)果對(duì)下一次讀取操作是肯定可見的。(在寫入volatile變量值之后,CPU緩存巾的內(nèi)容會(huì)被寫冋內(nèi)存;在讀取volatile變量時(shí),CPU緩存中的對(duì)應(yīng)內(nèi)容會(huì)被置為失效,重新從主存中進(jìn)行讀取),volatile不使用鎖,性能優(yōu)于synchronized關(guān)鍵詞。用來確保對(duì)一個(gè)變量
6、的修改被正確地傳播到其他線程中。例子:A線程是Worker,一直跑循環(huán),B線程調(diào)川setDone(true),A線程即停止任務(wù)1publicclassWorker{2privatevolatilebooleandone;3publicvoidsetDone(booleandone){4this,done=done;567891011publicvoidwork(){while(!done){//執(zhí)行任務(wù);例子:錯(cuò)誤使用。因?yàn)闆]有鎖的支持,volatile的修改不能依賴于當(dāng)前值,當(dāng)前值可能在其他線程中被修改。(Wor
7、ker是直接賦新值與當(dāng)前值無關(guān))2345publicvolatilestaticintcount=0;publicstaticvoidinc(){//這里延遲1毫秒,使得結(jié)果明顯try{6Thread,sleep(1);7}catch(InterruptedExceptione){8}9count++;10}11publicstaticvoidmain(String[]args){12//同時(shí)啟動(dòng)1000個(gè)線程,去進(jìn)行i++計(jì)算,看看實(shí)際結(jié)果13for(inti=0;i<1000;i++){14newThread(
8、newRunnable(){15?Override16publicvoidrun(){17Counter,inc();18}19}).start();20}21//這里每次運(yùn)行的值都有可能不同,可能不為100022System,out.println(〃運(yùn)行結(jié)果..Counter.count=〃+Counter,count);23}24}2、final關(guān)鍵詞