fields怎么讀(dashing怎么讀)
夕逆IT
- 前端設(shè)計(jì)
- 2023-08-13
- 112

大家好,fields怎么讀相信很多的網(wǎng)友都不是很明白,包括dashing怎么讀也是一樣,不過(guò)沒(méi)有關(guān)系,接下來(lái)就來(lái)為大家分享關(guān)于fields怎么讀和dashing怎么讀的...
大家好,fields怎么讀相信很多的網(wǎng)友都不是很明白,包括dashing怎么讀也是一樣,不過(guò)沒(méi)有關(guān)系,接下來(lái)就來(lái)為大家分享關(guān)于fields怎么讀和dashing怎么讀的一些知識(shí)點(diǎn),大家可以關(guān)注收藏,免得下次來(lái)找不到哦,下面我們開(kāi)始吧!
volatile關(guān)鍵字是什么
主要從以下三點(diǎn)講解volatile關(guān)鍵字:
volatile關(guān)鍵字是什么?volatile關(guān)鍵字能解決什么問(wèn)題?使用場(chǎng)景是什么?volatile關(guān)鍵字實(shí)現(xiàn)的原理?volatile關(guān)鍵字是什么?在Sun的JDK官方文檔是這樣形容volatile的:
TheJavaprogramminglanguageprovidesasecondmechanism,volatilefields,thatismoreconvenientthanlockingforsomepurposes.Afieldmaybedeclaredvolatile,inwhichcasetheJavaMemoryModelensuresthatallthreadsseeaconsistentvalueforthevariable.也就是說(shuō),如果一個(gè)變量加了volatile關(guān)鍵字,就會(huì)告訴編譯器和JVM的內(nèi)存模型:這個(gè)變量是對(duì)所有線程共享的、可見(jiàn)的,每次JVM都會(huì)讀取最新寫入的值并使其最新值在所有CPU可見(jiàn)。volatile可以保證線程的可見(jiàn)性并且提供了一定的有序性,但是無(wú)法保證原子性。在JVM底層volatile是采用內(nèi)存屏障來(lái)實(shí)現(xiàn)的。
通過(guò)這段話,我們可以知道volatile有兩個(gè)特性:
保證可見(jiàn)性、不保證原子性
禁止指令重排序原子性和可見(jiàn)性原子性是指一個(gè)操作或多個(gè)操作要么全部執(zhí)行并且執(zhí)行的過(guò)程不會(huì)被任何因素打斷,要么都不執(zhí)行。性質(zhì)和數(shù)據(jù)庫(kù)中事務(wù)一樣,一組操作要么都成功,要么都失敗??聪旅鎺讉€(gè)簡(jiǎn)單例子來(lái)理解原子性:
i==0;//1
j=i;//2
i++;//3
i=j+1;//4
在看答案之前,可以先思考一下上面四個(gè)操作,哪些是原子操作?哪些是非原子操作?
答案揭曉:
1——是:在Java中,對(duì)基本數(shù)據(jù)類型的變量賦值操作都是原子性操作(Java有八大基本數(shù)據(jù)類型,分別是byte,short,int,long,char,float,double,boolean)
2——不是:包含兩個(gè)動(dòng)作:讀取i值,將i值賦值給j
3——不是:包含了三個(gè)動(dòng)作:讀取i值,i+1,將i+1結(jié)果賦值給i
4——不是:包含了三個(gè)動(dòng)作:讀取j值,j+1,將j+1結(jié)果賦值給i
也就是說(shuō),只有簡(jiǎn)單的讀取、賦值(而且必須是將數(shù)字賦值給某個(gè)變量,變量之間的相互賦值不是原子操作)才是原子操作。
注:由于以前的操作系統(tǒng)是32位,64位數(shù)據(jù)(long型,double型)在Java中是8個(gè)字節(jié)表示,一共占用64位,因此需要分成兩次操作采用完成一個(gè)變量的賦值或者讀取操作。隨著64位操作系統(tǒng)越來(lái)越普及,在64位的HotSpotJVM實(shí)現(xiàn)中,對(duì)64位數(shù)據(jù)(long型,double型)做原子性處理(由于JVM規(guī)范沒(méi)有明確規(guī)定,不排除別的JVM實(shí)現(xiàn)還是按照32位的方式處理)。
在單線程環(huán)境中我們可以認(rèn)為上述步驟都是原子性操作,但是在多線程環(huán)境下,Java只保證了上述基本數(shù)據(jù)類型的賦值操作是原子性的,其他操作都有可能在運(yùn)算過(guò)程中出現(xiàn)錯(cuò)誤。為此在多線程環(huán)境下為了保證一些操作的原子性引入了鎖和synchronized等關(guān)鍵字。
上面說(shuō)到volatile關(guān)鍵字保證了變量的可見(jiàn)性,不保證原子性。原子性已經(jīng)說(shuō)了,下面說(shuō)下可見(jiàn)性。
可見(jiàn)性其實(shí)和Java內(nèi)存模型的設(shè)定有關(guān):Java內(nèi)存模型規(guī)定所有的變量都是存在主存(線程共享區(qū)域)當(dāng)中,每個(gè)線程都有自己的工作內(nèi)存(私有內(nèi)存)。線程對(duì)變量的所有操作都必須在工作內(nèi)存中進(jìn)行,而不直接對(duì)主存進(jìn)行操作。并且每個(gè)線程不能訪問(wèn)其他線程的工作內(nèi)存。
舉個(gè)簡(jiǎn)單栗子:
比如上面i++操作,在Java中,執(zhí)行i++語(yǔ)句:
執(zhí)行線程首先從主存中讀取i(原始值)到工作內(nèi)存中,然后在工作內(nèi)存中執(zhí)行運(yùn)算+1操作(主存的i值未變),最后將運(yùn)算結(jié)果刷新到主存中。
數(shù)據(jù)運(yùn)算是在執(zhí)行線程的私有內(nèi)存中進(jìn)行的,線程執(zhí)行完運(yùn)算后,并不一定會(huì)立即將運(yùn)算結(jié)果刷新到主存中(雖然最后一定會(huì)更新主存),刷新到主存動(dòng)作是由CPU自行選擇一個(gè)合適的時(shí)間觸發(fā)的。假設(shè)數(shù)值未更新到主存之前,當(dāng)其他線程去讀取時(shí)(而且優(yōu)先讀取的是工作內(nèi)存中的數(shù)據(jù)而非主存),此時(shí)主存中可能還是原來(lái)的舊值,就有可能導(dǎo)致運(yùn)算結(jié)果出錯(cuò)。
以下代碼是測(cè)試代碼:
packagecom.wupx.test;/**
*@authorwupx
*@date2019/10/31
*/
publicclassVolatileTest{
privatebooleanflag=false;
classThreadOneimplementsRunnable{
@Override
publicvoidrun(){
while(!flag){
System.out.println("執(zhí)行操作");
try{
Thread.sleep(1000L);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
System.out.println("任務(wù)停止");
}
}
classThreadTwoimplementsRunnable{
@Override
publicvoidrun(){
try{
Thread.sleep(2000L);
System.out.println("flag狀態(tài)改變");
flag=true;
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
publicstaticvoidmain(String[]args){
VolatileTesttestVolatile=newVolatileTest();
Threadthread1=newThread(testVolatile.newThreadOne());
Threadthread2=newThread(testVolatile.newThreadTwo());
thread1.start();
thread2.start();
}
}
上述結(jié)果有可能在線程2執(zhí)行完flag=true之后,并不能保證線程1中的while能立即停止循環(huán),原因在于flag狀態(tài)首先是在線程2的私有內(nèi)存中改變的,刷新到主存的時(shí)機(jī)不固定,而且線程1讀取flag的值也是在自己的私有內(nèi)存中,而線程1的私有內(nèi)存中flag仍未false,這樣就有可能導(dǎo)致線程仍然會(huì)繼續(xù)while循環(huán)。運(yùn)行結(jié)果如下:
執(zhí)行操作執(zhí)行操作
執(zhí)行操作
flag狀態(tài)改變
任務(wù)停止
避免上述不可預(yù)知問(wèn)題的發(fā)生就是用volatile關(guān)鍵字修飾flag,volatile修飾的共享變量可以保證修改的值會(huì)在操作后立即更新到主存里面,當(dāng)有其他線程需要操作該變量時(shí),不是從私有內(nèi)存中讀取,而是強(qiáng)制從主存中讀取新值。即一個(gè)線程修改了某個(gè)變量的值,這新值對(duì)其他線程來(lái)說(shuō)是立即可見(jiàn)的。
指令重排序一般來(lái)說(shuō),處理器為了提高程序運(yùn)行效率,可能會(huì)對(duì)輸入代碼進(jìn)行優(yōu)化,它不保證程序中各個(gè)語(yǔ)句的執(zhí)行先后順序同代碼中的順序一致,但是它會(huì)保證程序最終執(zhí)行結(jié)果和代碼順序執(zhí)行的結(jié)果是一致的。
比如下面的代碼
inti=0;
booleanflag=false;
i=1;//1
flag=true;//2
代碼定義了一個(gè)int型變量,定義了一個(gè)boolean類型變量,然后分別對(duì)兩個(gè)變量進(jìn)行賦值操作。從代碼順序上看,語(yǔ)句1是在語(yǔ)句2前面的,那么JVM在真正執(zhí)行這段代碼的時(shí)候會(huì)保證語(yǔ)句1一定會(huì)在語(yǔ)句2前面執(zhí)行嗎?不一定,為什么呢?這里可能會(huì)發(fā)生指令重排序(InstructionReorder)。
語(yǔ)句1和語(yǔ)句2誰(shuí)先執(zhí)行對(duì)最終的程序結(jié)果并沒(méi)有影響,那么就有可能在執(zhí)行過(guò)程中,語(yǔ)句2先執(zhí)行而語(yǔ)句1后執(zhí)行。
但是要注意,雖然處理器會(huì)對(duì)指令進(jìn)行重排序,但是它會(huì)保證程序最終結(jié)果會(huì)和代碼順序執(zhí)行結(jié)果相同,那么它靠什么保證的呢?再看下面一個(gè)例子:
inta=10;//1intr=2;//2
a=a+3;//3
r=a*a;//4
這段代碼執(zhí)行的順序可能是1->2->3->4或者是2->1->3->4,但是3和4的執(zhí)行順序是不會(huì)變的,因?yàn)樘幚砥髟谶M(jìn)行重排序時(shí)是會(huì)考慮指令之間的數(shù)據(jù)依賴性,如果一個(gè)指令I(lǐng)nstruction2必須用到Instruction1的結(jié)果,那么處理器會(huì)保證Instruction1會(huì)在Instruction2之前執(zhí)行。
雖然重排序不會(huì)影響單個(gè)線程內(nèi)程序執(zhí)行的結(jié)果,但是多線程呢?下面看一個(gè)例子:
//線程1Stringconfig=initConfig();//1
booleaninited=true;//2
//線程2
while(!inited){
sleep();
}
doSomeThingWithConfig(config);
上面代碼中,由于語(yǔ)句1和語(yǔ)句2沒(méi)有數(shù)據(jù)依賴性,因此可能會(huì)被重排序。假如發(fā)生了重排序,在線程1執(zhí)行過(guò)程中先執(zhí)行語(yǔ)句2,而此時(shí)線程2會(huì)以為初始化工作已經(jīng)完成,那么就會(huì)跳出while循環(huán),去執(zhí)行doSomeThingWithConfig(config)方法,而此時(shí)config并沒(méi)有被初始化,就會(huì)導(dǎo)致程序出錯(cuò)。
從上面可以看出,指令重排序不會(huì)影響單個(gè)線程的執(zhí)行,但是會(huì)影響到線程并發(fā)執(zhí)行的正確性。
那么volatile關(guān)鍵字修飾的變量禁止重排序的含義是:
當(dāng)程序執(zhí)行到volatile變量的讀操作或者寫操作時(shí),在其前面的操作肯定已經(jīng)全部進(jìn)行,且對(duì)后面的操作可見(jiàn),在其后面的操作肯定還沒(méi)有進(jìn)行
在進(jìn)行指令優(yōu)化時(shí),不能將volatile變量之前的語(yǔ)句放在對(duì)volatile變量的讀寫操作之后,也不能把volatile變量后面的語(yǔ)句放到其前面執(zhí)行舉個(gè)栗子:
x=0;//1
y=1;//2
volatilez=2;//3
x=4;//4
y=5;//5
變量z為volatile變量,那么進(jìn)行指令重排序時(shí),不會(huì)將語(yǔ)句3放到語(yǔ)句1、語(yǔ)句2之前,也不會(huì)將語(yǔ)句3放到語(yǔ)句4、語(yǔ)句5后面。但是語(yǔ)句1和語(yǔ)句2、語(yǔ)句4和語(yǔ)句5之間的順序是不作任何保證的,并且volatile關(guān)鍵字能保證,執(zhí)行到語(yǔ)句3時(shí),語(yǔ)句1和語(yǔ)句2必定是執(zhí)行完畢了的,且語(yǔ)句1和語(yǔ)句2的執(zhí)行結(jié)果是對(duì)語(yǔ)句3、語(yǔ)句4、語(yǔ)句5是可見(jiàn)的。
回到之前的例子:
//線程1
Stringconfig=initConfig();//1
volatilebooleaninited=true;//2
//線程2
while(!inited){
sleep();
}
doSomeThingWithConfig(config);
之前說(shuō)這個(gè)例子提到有可能語(yǔ)句2會(huì)在語(yǔ)句1之前執(zhí)行,那么就可能導(dǎo)致執(zhí)行doSomThingWithConfig()方法時(shí)就會(huì)導(dǎo)致出錯(cuò)。
這里如果用volatile關(guān)鍵字對(duì)inited變量進(jìn)行修飾,則可以保證在執(zhí)行語(yǔ)句2時(shí),必定能保證config已經(jīng)初始化完畢。
volatile應(yīng)用場(chǎng)景synchronized關(guān)鍵字是防止多個(gè)線程同時(shí)執(zhí)行一段代碼,那么就會(huì)很影響程序執(zhí)行效率,而volatile關(guān)鍵字在某些情況下性能要優(yōu)于synchronized,但是要注意volatile關(guān)鍵字是無(wú)法替代synchronized關(guān)鍵字的,因?yàn)関olatile關(guān)鍵字無(wú)法保證操作的原子性。通常來(lái)說(shuō),使用volatile必須具備以下三個(gè)條件:
對(duì)變量的寫入操作不依賴變量的當(dāng)前值,或者能確保只有單個(gè)線程更新變量的值
該變量不會(huì)與其他狀態(tài)變量一起納入不變性條件中在訪問(wèn)變量時(shí)不需要加鎖上面的三個(gè)條件只需要保證是原子性操作,才能保證使用volatile關(guān)鍵字的程序在高并發(fā)時(shí)能夠正確執(zhí)行。建議不要將volatile用在getAndOperate場(chǎng)合,僅僅set或者get的場(chǎng)景是適合volatile的。
常用的兩個(gè)場(chǎng)景是:
狀態(tài)標(biāo)記量
volatilebooleanflag=false;
while(!flag){
doSomething();
}
publicvoidsetFlag(){
flag=true;
}
volatilebooleaninited=false;
//線程1
context=loadContext();
inited=true;
//線程2
while(!inited){
sleep();
}
doSomethingwithconfig(context);
DCL雙重校驗(yàn)鎖-單例模式publicclassSingleton{
privatevolatilestaticSingletoninstance=null;
privateSingleton(){
}
/**
*當(dāng)?shù)谝淮握{(diào)用getInstance()方法時(shí),instance為空,同步操作,保證多線程實(shí)例唯一
*當(dāng)?shù)谝淮魏笳{(diào)用getInstance()方法時(shí),instance不為空,不進(jìn)入同步代碼塊,減少了不必要的同步
*/
publicstaticSingletongetInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=newSingleton();
}
}
}
returninstance;
}
}
使用volatile的原因在上面解釋重排序時(shí)已經(jīng)講過(guò)了。主要在于instance=newSingleton(),這并非是一個(gè)原子操作,在JVM中這句話做了三件事情:
給instance分配內(nèi)存
調(diào)用Singleton的構(gòu)造函數(shù)來(lái)初始化成員變量將instance對(duì)象指向分配的內(nèi)存庫(kù)存空間(執(zhí)行完這步instance就為非null了)但是JVM即時(shí)編譯器中存在指令重排序的優(yōu)化,也就是說(shuō)上面的第二步和第三步順序是不能保證的,最終的執(zhí)行順序可能是1-2-3,也可能是1-3-2。如果是后者,線程1在執(zhí)行完3之后,2之前,被線程2搶占,這時(shí)instance已經(jīng)是非null(但是并沒(méi)有進(jìn)行初始化),所以線程2返回instance使用就會(huì)報(bào)空指針異常。
volatile特性是如何實(shí)現(xiàn)的呢?前面講述了關(guān)于volatile關(guān)鍵字的一些使用,下面我們來(lái)探討一下volatile到底如何保證可見(jiàn)性和禁止指令重排序的。
在《深入理解Java虛擬機(jī)》這本書中說(shuō)道:
觀察加入volatile關(guān)鍵字和沒(méi)有加入volatile關(guān)鍵字時(shí)所生成的匯編代碼發(fā)現(xiàn),加入volatile關(guān)鍵字時(shí),會(huì)多出一個(gè)lock前綴指令。接下來(lái)舉個(gè)栗子:
volatile的Integer自增(i++),其實(shí)要分成3步:
讀取volatile變量值到local
增加變量的值把local的值寫回,讓其它的線程可見(jiàn)這3步的JVM指令為:
mov0xc(%r10),%r8d;Load
inc%r8d;Increment
mov%r8d,0xc(%r10);Store
lockaddl$0x0,(%rsp);StoreLoadBarrier
lock前綴指令實(shí)際上相當(dāng)于一個(gè)內(nèi)存屏障(也叫內(nèi)存柵欄),內(nèi)存屏障會(huì)提供3個(gè)功能:
它確保指令重排序時(shí)不會(huì)把其后面的指令排到內(nèi)存屏障之前的位置,也不會(huì)把前面的指令排到內(nèi)存屏障的后面;即在執(zhí)行到內(nèi)存屏障這句指令時(shí),在它前面的操作已經(jīng)全部完成(滿足禁止重排序)
它會(huì)強(qiáng)制將對(duì)緩存的修改操作立即寫入主存(滿足可見(jiàn)性)如果是寫操作,它會(huì)導(dǎo)致其他CPU中對(duì)應(yīng)的緩存行無(wú)效(滿足可見(jiàn)性)volatile變量規(guī)則是happens-before(先行發(fā)生原則)中的一種:對(duì)一個(gè)變量的寫操作先行發(fā)生于后面對(duì)這個(gè)變量的讀操作。(該特性可以很好解釋DCL雙重檢查鎖單例模式為什么使用volatile關(guān)鍵字來(lái)修飾能保證并發(fā)安全性)
總結(jié)變量聲明為volatile類型時(shí),編譯器與運(yùn)行時(shí)都會(huì)注意到這個(gè)變量是共享的,不會(huì)將該變量上的操作與其他內(nèi)存操作一起重排序。volatile變量不會(huì)被緩存在寄存器或者對(duì)其他處理器不可見(jiàn)的地方,因此在讀取volatile類型的變量時(shí)總會(huì)返回最新寫入的值。
在訪問(wèn)volatile變量時(shí)不會(huì)執(zhí)行加鎖操作,也就不會(huì)使執(zhí)行線程阻塞,因此volatile變量是比sychronized關(guān)鍵字更輕量級(jí)的同步機(jī)制。
加鎖機(jī)制既可以確??梢?jiàn)性和原子性,而volatile變量只能確??梢?jiàn)性。
想了解更多Java相關(guān),百度搜索圈T社區(qū)www.aiquanti.com,免費(fèi)視頻教程。純干貨
讀原版哈利波特的好處
讀原版哈利波特這本書有很多好處。首先,它可以幫助讀者培養(yǎng)閱讀興趣,提高閱讀水平,提高語(yǔ)言能力。其次,通過(guò)對(duì)魔法世界的描述,可以讓讀者想象力得到鍛煉,增強(qiáng)創(chuàng)造力。此外,哈利波特也傳遞了積極的價(jià)值觀,例如友情、正義、勇氣等,有助于塑造讀者的人生觀。最后,哈利波特系列的全球影響力也促進(jìn)了跨文化溝通,有利于推動(dòng)文化交流和理解。
nine和pig和rice發(fā)音相同嗎
如果是在問(wèn)三個(gè)單詞中字母i的發(fā)音是否相同,nine和rice是相同的。
nine——字母i的發(fā)音為字母本身音,音標(biāo)[ai]
pig——字母i的發(fā)音為短元音,音標(biāo)[i]
rice——字母i的發(fā)音為字母本身音,音標(biāo)[ai]
房車自駕游怎么樣
在歐美、澳洲會(huì)很爽,但在國(guó)內(nèi)房車營(yíng)地等相關(guān)配套設(shè)施還跟不上,洗澡、用電、停車、安全等多方面都存在問(wèn)題。我去年十一月份租了一臺(tái)房車從重慶自駕去海南環(huán)島游,因?yàn)榉寇嚬靖慊顒?dòng),租金只要1塊錢每天,這就再次體現(xiàn)出我自由職業(yè)者的好處了,頭天晚上看到朋友圈有人發(fā)活動(dòng),當(dāng)場(chǎng)預(yù)定,第二天帶上家人,帶上電腦就出發(fā)了。
租金是便宜,但押金交了五萬(wàn),油費(fèi)和過(guò)路費(fèi)一共3000,平均每公里成本1塊吧,2.7的海獅,百公里差不多16個(gè)油,車子還到三亞坐飛機(jī)回的重慶,機(jī)票200,再次體現(xiàn)自由職業(yè)者淡季出行的福利。
全程住的酒店,一天都沒(méi)有住車上,洗澡不方便。但這種方式還是很適合帶孩子和老人一起旅行,他們不累,隨時(shí)可以睡覺(jué)。10天行程,一家五口,吃住行玩一共用了15000,性價(jià)比還是非常高了,孩子特別喜歡,畢竟房車感覺(jué)很新奇。
淡季的三亞還是很不錯(cuò)的,海鮮也不貴,特別推薦海棠灣萬(wàn)豪萬(wàn)麗酒店,豪華海景標(biāo)準(zhǔn)間780一晚,性價(jià)比超高,私家海灘,清爽感動(dòng)世界!
近三年的夢(mèng)想是買一臺(tái)能越野的小房車,在孩子寒暑假時(shí)一家三口去環(huán)球旅行,我的朋友圈里就有這么一家子,已經(jīng)跑了三年十多萬(wàn)公里了,靠給媒體供稿和商業(yè)贊助為生,孩子基本上是在車上長(zhǎng)大的,很有意義的童年。
一個(gè)佘一個(gè)田讀什么
一個(gè)佘一個(gè)田讀畬。畬是一個(gè)多音字,漢語(yǔ)拼音為shē和yú,字形結(jié)構(gòu)為上下結(jié)構(gòu),共計(jì)12畫。一般讀作shē,意思是火耕地,指粗放耕種的田地。畬也是我國(guó)的一個(gè)少數(shù)民族,畬族,主要居住在浙江省和福建省。當(dāng)畬讀住yú時(shí),是指開(kāi)墾了二、三年的熟田。
一個(gè)土一個(gè)中念什么
埝拼音:niàn
田里或淺水里用于擋水的土埂〖alowbankbetweenfields〗。如:打埝
淮北鹽場(chǎng)交貨、換船的地方叫埝〖dock〗。也稱為堰。如:太平埝;臨浦埝埝
沂蒙地區(qū)方言,地方的意思。
關(guān)于fields怎么讀到此分享完畢,希望能幫助到您。
本文鏈接:http:///qianduan/4517.html