面試官:連線程不安全都說不出個所以然,怎麼寫出高效穩定的程序

java技術分享 發佈 2019-12-28T21:20:18+00:00

程式設計師面試時,線程安全知識點經常會遇到。小洪是一名java程式設計師,工作兩年多了,最近去了某網際網路公司面試,面試時,面試官問了這樣一個問題:面試官:StringBuilder和StringBuffer有什麼區別?

程式設計師面試時,線程安全知識點經常會遇到。

小洪是一名java程式設計師,工作兩年多了,最近去了某網際網路公司面試,面試時,面試官問了這樣一個問題:

面試官:StringBuilder和StringBuffer有什麼區別?

小洪:StringBuilder線程不安全的,StringBuffer是線程安全的

面試官:能舉個例子說說StringBuilder是怎麼線程不安全的嗎?

小洪:……

小洪有點懵了,平時在用在使用StringBuilder追加字符時,只是簡單的用,只知道它是不是線程安全,至於不安全在哪裡,小洪並沒有去關注。

見小洪沒有作答,面談時面試官又問,StringBuffer哪裡安全了,小洪也回答不出個所以然。

面試官:你都工作兩年了,這個都不知道,怎麼寫出穩定的程序啊?小洪一臉的無助,不過確實不應該,類似StringBuilder常見的知識點,平時應該不會少用,應該掌握才對。

剛畢業的時候,面試時也遇到了類似關於StringBuild的問題,關於StringBuild線程不安全簡單來說StringBuilder沒有加鎖,而StringBuffer有加鎖。面試時,這樣回答固然沒有錯,但要是能進一步分析個所以然那就更好了,相信能給面試官留下更好的印象。

我們舉個例子來驗證下

1. 分別用500個線程寫StringBuffer和StringBuilder,

2. 保證在各自500個線程執行完後列印StringBuffer和StringBuilder字符串長度

3. 檢驗運行結果。

測試

我們創建了500個線程,每個線程往StringBuilder對象裡面append一個字符p。正常情況下代碼應該輸出500,但是實際運行結果是什麼呢?

測試結果

我們看到字符串長度有時候是496,有時候是498,小於預期值500。而當我們把StringBuilder換成StringBuffer不管運行多少次,結果的值都是500,從這個例子我們可以得出StringBuffer線程安全,StringBuilder線程不安全得到了證明。

為什麼輸出值跟預期值不一樣,源碼分析

為什麼會小於期望值,我們來看下StringBuilder的源碼

StringBuilder的append()方法調用的父類AbstractStringBuilder的append()方法,我們來看下這個方法具體做了什麼。

細心的你會發現count += len;這一行代碼並不是一個原子操作。

假設count的值為10,len值為1,這時候有兩個線程同時執行到了這行代碼,count值都是10,執行完後將結果賦值給count,這兩個線程執行完後count值為11,而不是12。這就是為什麼測試代碼輸出的值要小於我們的期望值500的原因了。

而當我們換成StringBuffer類是,為什麼能保證輸出的是500,我們看一下StringBuffer源碼就會發現所有寫操作都有synchronized修飾了

而StringBuilder的寫操作則沒有使用synchronized進行修飾。

StringBuilder類的append方法

@Override

public StringBuilder append(String str) {

super.append(str);

return this;

}

StringBuffer 類的append方法

@Override

public synchronized StringBuffer append(String str) {

toStringCache = null;

super.append(str);

return this;

}

關於StringBuilder不是線程安全的例子就分析到這。筆者覺得類似這樣的基礎知識點需要在平時學習中不斷摸索,不斷去探索實踐,不斷運用,才能在工作中更好地解決問題。由於筆者水平有限,文中紕漏之處在所難免,權當拋磚引玉,不妥之處,敬請讀者不吝賜教,是為至盼。

來源:https://www.toutiao.com/i6761277756698264071/

喜歡對你有幫助的話記得加個關注不迷路哦

還有關注我私信回復【資料】可以領取到一些個人收集的面試及電子書資料,或許對你有幫助!

關鍵字: