Java多線程對于成員變量和局部變量的影響

今天配合同事一起和外部系統(tǒng)進行聯(lián)調(diào)測試,其實昨天我們已經(jīng)成功走通了一遍。今天同事得到對方反饋系統(tǒng)可能有一個潛在的問題,所以就又嚴(yán)格地聯(lián)調(diào)了一遍负间。這一遍偶妖,我也是一遍又一遍地盯日志,關(guān)注告警郵件政溃。正是在這一遍聯(lián)調(diào)系統(tǒng)中趾访,我發(fā)現(xiàn)了一個小問題,程序里面一封相同內(nèi)容的通知郵件董虱,幾乎是同一個時間發(fā)送了兩次扼鞋。

通過分析日志外加比對代碼,終于找到問題愤诱,是遇到線程安全問題引起的云头。下面和大家分享一下,偽代碼:

public class Email{
  private String emailContent;
  @Async
  public void sendEmail(){
      "send email" + emailContent;
  }
}
//Email類的實例被Spring容器管理转锈,只有一個實例emailInstance盘寡。
public class TestDemo{
  @Resource
  Email emailInstance;
  @Async
  public void testMethod(){
      lock();
        //處理業(yè)務(wù)邏輯楚殿,同時操作emailInstance.emailContent;
        operationBs();
        emailInstance. sendEmail();
      unlock();
  }
}

問題原因復(fù)述:testMethod方法為防止多線程同時操作撮慨,在此處使用了鎖,而為了確保發(fā)送郵件不影響主程序的執(zhí)行時間脆粥,所以在調(diào)用sendEmail方法時砌溺,另行開辟了異步線程處理。正是這個方法允許了異步線程處理变隔,所以當(dāng)?shù)谝粋€線程釋放鎖后规伐,而異步線程尚未完成郵件發(fā)送時,第二個獲得鎖并執(zhí)行sendEmail方法時匣缘,開啟了新的異步線程處理郵件發(fā)送猖闪,這樣就出現(xiàn)了多個線程共同使用emailInstance對象,并同時操作emailInstance的成員變量emailContent肌厨。

因為如果一個變量是成員變量培慌,那么多個線程對同一個對象的成員變量進行操作時,他們對該成員變量的操作是彼此影響的(也就是說一個線程對成員變量的改變會影響到另一個線程)柑爸。這樣就會出現(xiàn)上述發(fā)送相同內(nèi)容郵件的情況吵护。

理論講解:JAVA 多線程同時調(diào)用單例模式的對象時,該對象中的對成員變量與局部變量是否會受到多個線程的影響表鳍?

當(dāng)多個線程對同一個單例對象的同一個成員變量進行操作時馅而,它們對該成員變量的操作是彼此互相影響的(也就是說一個線程對該成員變量的改變會影響到另一個線程) 。對于成員變量的操作譬圣,可以使用ThreadLocal來保證線程安全瓮恭。

而多線程調(diào)用同一個對象的同一個方法時,每個線程會對方法內(nèi)部的局部變量都是在線程自己獨立的內(nèi)存區(qū)域進行的厘熟,也就是說在每個線程的獨立內(nèi)存中都一個局部變量的拷貝屯蹦,這樣一個線程對同一個單例對象的同一方法內(nèi)的局部變量的改變就不會影響到其他線程中的局部變量诸衔,所以是線程安全的。

總結(jié)颇玷,局部變量不會受多線程影響笨农,成員變量會受到多線程影響。多個線程調(diào)用同一個對象的同一個方法時帖渠,如果方法里無成員變量谒亦,那么不受任何影響;如果方法里有成員變量空郊,只有讀操作份招,不受影響,存在寫操作狞甚,考慮多線程影響值锁摔。

解決方案:

  1. 簡化方案,去掉Email中sendEmail方法上@Async注解哼审,也就是說將處理業(yè)務(wù)邏輯和發(fā)送郵件合并為同步操作谐腰,這樣就保證了同一時間只會有一個線程操作成員變量,這樣也就避免了線程安全問題涩盾。但注意這是以犧牲核心業(yè)務(wù)邏輯的處理時間來換得安全十气。
  2. 將操作成員變量,調(diào)整為操作局部變量春霍。

參考文檔:
Java 多線程(四) 多線程訪問成員變量與局部變量

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末砸西,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子址儒,更是在濱河造成了極大的恐慌芹枷,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莲趣,死亡現(xiàn)場離奇詭異鸳慈,居然都是意外死亡,警方通過查閱死者的電腦和手機妖爷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門蝶涩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人絮识,你說我怎么就攤上這事绿聘。” “怎么了次舌?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵熄攘,是天一觀的道長。 經(jīng)常有香客問我彼念,道長挪圾,這世上最難降的妖魔是什么浅萧? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮哲思,結(jié)果婚禮上洼畅,老公的妹妹穿的比我還像新娘。我一直安慰自己棚赔,他們只是感情好帝簇,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著靠益,像睡著了一般丧肴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胧后,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天芋浮,我揣著相機與錄音,去河邊找鬼壳快。 笑死纸巷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的濒憋。 我是一名探鬼主播何暇,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼陶夜,長吁一口氣:“原來是場噩夢啊……” “哼凛驮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起条辟,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤黔夭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后羽嫡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體本姥,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年杭棵,在試婚紗的時候發(fā)現(xiàn)自己被綠了婚惫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡魂爪,死狀恐怖先舷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滓侍,我是刑警寧澤蒋川,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站撩笆,受9級特大地震影響捺球,放射性物質(zhì)發(fā)生泄漏缸浦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一氮兵、第九天 我趴在偏房一處隱蔽的房頂上張望裂逐。 院中可真熱鬧,春花似錦泣栈、人聲如沸絮姆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽篙悯。三九已至,卻和暖如春铃绒,著一層夾襖步出監(jiān)牢的瞬間鸽照,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工颠悬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留矮燎,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓赔癌,卻偏偏與公主長得像诞外,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子灾票,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354