聲明一個(gè)static int 變量,在多個(gè)線程中對(duì)他進(jìn)行操作,就會(huì)出現(xiàn)數(shù)據(jù)異常的問(wèn)題,
那么我們?cè)谌粘G闆r下應(yīng)該如何正常,正確的使用static關(guān)鍵字呢,是一定要和final關(guān)鍵字聯(lián)合使用嗎,還是什么樣的變量可以用static聲明什么樣的最好不要
----------------------------------------------------------------下面是我獲得到的我想要的答案
就是我們平常web開發(fā)中,很少會(huì)使用主動(dòng)使用多線程,但是還有一種多線程情況就是每個(gè)用戶都是一個(gè)線程,當(dāng)訪問(wèn)量很大的時(shí)候是不是也就是多線程了呢,可是這種時(shí)候你使用非靜態(tài)成員變量是沒(méi)問(wèn)題的,因?yàn)槊總€(gè)用戶都是不同的實(shí)例,每個(gè)用戶都是new的新的類對(duì)象,所以類中的變量也都是互相不干擾的,也就是線程安全的,但如果是靜態(tài)變量,就是多用戶共享,也就是多線程共享,所以多個(gè)用戶同時(shí)修改數(shù)據(jù)時(shí)就會(huì)出現(xiàn)問(wèn)題,難道我們平常開發(fā)中每次使用靜態(tài)變量都要考慮線程安全問(wèn)題嗎
— coder94 · 35 分鐘前
日常web開發(fā)中如果不使用多線程,是不用考慮線程安全的問(wèn)題的對(duì)吧。
但是如果使用了靜態(tài)變量,即使不開啟多線程,也要考慮多線程安全問(wèn)題對(duì)嗎,因?yàn)槊總€(gè)用戶都是多個(gè)線程,都會(huì)同時(shí)操作靜態(tài)變量
— coder94 · 28 分鐘前
大哥,你這是另一個(gè)問(wèn)題了,我是針對(duì)你剛剛的問(wèn)題答的。如果要針對(duì)你現(xiàn)在的問(wèn)題,平常不管是用Spring還是Servlet,都是單例的,會(huì)在不同請(qǐng)求線程之間共享,所以其不管是實(shí)例變量還是靜態(tài)變量都會(huì)被共享。如果確定要共享,那么需要確保線程安全性。但是如果要在多個(gè)請(qǐng)求間共享可變變量呢?根據(jù)業(yè)務(wù)場(chǎng)景不同而不同,可以采用我上述提到的java自帶的機(jī)制及加鎖等,也可以采用消息隊(duì)列,數(shù)據(jù)庫(kù),redis.
— xbynet · 26 分鐘前
還有一點(diǎn)要糾正你一下,不是只有靜態(tài)變量才會(huì)被共享,一個(gè)實(shí)例變量被多個(gè)線程使用時(shí)也是被共享的。
— xbynet · 24 分鐘前
回復(fù) coder94:
日常web開發(fā),每個(gè)http請(qǐng)求一個(gè)線程。如果你不涉及共享可變變量,是不需要考慮線程安全性的。如果你想共享一些信息,對(duì)于傳統(tǒng)單體應(yīng)用來(lái)說(shuō),簡(jiǎn)單點(diǎn)可以通過(guò)session來(lái)共享。 還有點(diǎn),你關(guān)于線程安全的東西,建議你去補(bǔ)補(bǔ)理論基礎(chǔ)。推薦一本經(jīng)典書:<<Java并發(fā)編程實(shí)戰(zhàn)>> 國(guó)外大牛寫的,不是國(guó)內(nèi)的那本。
— xbynet · 13 分鐘前
回復(fù) xbynet:
好的 ,謝謝 ,我剛試了下,您說(shuō)的對(duì),不是靜態(tài)變量也會(huì)被共享
— coder94 · 12 分鐘前
類中的靜態(tài)變量在程序運(yùn)行期間,其內(nèi)存空間對(duì)所有該類的對(duì)象實(shí)例而言是共享的,為了節(jié)省系統(tǒng)內(nèi)存開銷、共享資源,應(yīng)該將一些變量聲明為靜態(tài)變量。
代碼一:
public class MemoryTest {
static class Data{
private int week;
private String name;
Data(int i, String s){
week = i;
name = s;
}
}
Data weeks[] = {
new Data(1,"monday"),
new Data(2,"Tuesday"),
new Data(3,"Wednesday"),
new Data(4,"Thursday"),
new Data(5,"Friday"),
new Data(6,"Saturday"),
new Data(7,"Sunday")
};
public static void main(String[] args) {
final int N = 20000;
MemoryTest test = null;
for (int i = 0; i <=N; i++) {
test = new MemoryTest();
}
System.out.println(test.weeks.length);
}
}
代碼二:
public class MemoryTest {
static class Data{
private int week;
private String name;
Data(int i, String s){
week = i;
name = s;
}
}
static Data weeks[] = {
new Data(1,"monday"),
new Data(2,"Tuesday"),
new Data(3,"Wednesday"),
new Data(4,"Thursday"),
new Data(5,"Friday"),
new Data(6,"Saturday"),
new Data(7,"Sunday")
};
public static void main(String[] args) {
final int N = 20000;
MemoryTest test = null;
for (int i = 0; i <=N; i++) {
test = new MemoryTest();
}
System.out.println(test.weeks.length);
}
}
應(yīng)該發(fā)現(xiàn)上面那兩個(gè)類的區(qū)別吧
Data weeks[] 與 static Data weeks[]
代碼一會(huì)在內(nèi)存中保存20000個(gè)weeks的副本,而代碼二則在內(nèi)存中保存1個(gè)weeks的副本,然后共享該副本,這樣的話就不會(huì)造成內(nèi)存的浪費(fèi)。
雖然靜態(tài)的變量能節(jié)約大量的內(nèi)存,但是并不是所有的地方都適合用,建議在下列條件都符合的情況下,盡量用靜態(tài)變量:
(1)變量所包含的對(duì)象體積較大,占用內(nèi)存較多。
(2)變量所包含的對(duì)象生命周期較長(zhǎng)。
(3)變量所包含的對(duì)象數(shù)據(jù)穩(wěn)定。
(4)該類的對(duì)象實(shí)例有對(duì)該變量所包含的對(duì)象的共享需求。
如果變量不具備上述特點(diǎn),建議不要輕易使用靜態(tài)變量。
最后,再提一點(diǎn)內(nèi)存的優(yōu)化,就是有關(guān)對(duì)象的重用,比如:對(duì)象池和數(shù)據(jù)庫(kù)連接池等。那樣的話,是很節(jié)約內(nèi)存空間的,不過(guò),在用的時(shí)候要考慮各個(gè)方面,比如:運(yùn)行環(huán)境的內(nèi)存資源的限制等。為了防止對(duì)象池中的對(duì)象過(guò)多,要記得清除。
這是線程安全的問(wèn)題,建議了解一下線程安全機(jī)制。線程安全性比較關(guān)鍵的兩個(gè)點(diǎn):內(nèi)存可見性和操作原子性
如果你不修改值,可以使用private static final int ,final可以保證內(nèi)存可見性語(yǔ)義。對(duì)于原生變量,final修飾后不可更改,從而也不存在操作原子性的問(wèn)題。
如果你只是想單純地進(jìn)行賦值,而不進(jìn)行復(fù)合操作,如i++,i=i+1之類的。那么可以使用volatile int. volatile可以確保內(nèi)存可見性,但是無(wú)法確保原子性,所以不支持復(fù)合操作的線程安全性。
如果你想進(jìn)行復(fù)合操作,可以使用AtomicInteger這個(gè)原子類,支持CAS操作,可確保內(nèi)存可見性和操作原子性。
為什么會(huì)存在線程安全性問(wèn)題?
簡(jiǎn)要說(shuō)一下,java中所有的線程都共享jvm進(jìn)程的虛擬內(nèi)存地址空間。一般的共享變量存放在這共享區(qū)域中。但是每個(gè)線程還有自己的本地緩存,在線程讀取變量時(shí),會(huì)在其本地拷貝一份副本進(jìn)行操作,這樣就會(huì)導(dǎo)致共享內(nèi)存和本地副本存在不一致的情況。
如果想深入理解,可以看一下cpu的緩存機(jī)制.
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國(guó)家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
北大課工場(chǎng)是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國(guó)家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國(guó)制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級(jí)產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國(guó)職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫(kù),具有快速界面開發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁(yè)制作和網(wǎng)頁(yè)游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問(wèn),美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。