執行緒安全問題及優化
阿新 • • 發佈:2019-01-09
前一段時間一直在加班加點的研究新技術,研究新語言,以至於兩個月沒更新部落格、總結知識,能堅持果然不容易
前一段時間一直在做一個日誌訊息傳送的功能元件,最終被打成單獨jar包引用,其中涉及到大量的執行緒安全問題,頭一次這麼深入的去研究執行緒,有些手足無措,最終還是按照需求做了出來,以此記錄總結遇到的問題
執行緒鎖優化問題
public static synchronized int cleanDate(int type) { if (type == 0) { sysThread.exit = false; int num = httpPost(sysLogDataList); sysLogDataList = Collections.synchronizedList(new ArrayList<>()); dataMap = new HashMap<>(); return num; } else { apiThread.exit = false; int num = httpPost(apiLogDataList); apiLogDataList = Collections.synchronizedList(new ArrayList<>()); return num; } }
如上程式碼,在方法中加入synchronized關鍵字修飾,可以保證同一時間只有一個執行緒能訪問該方法(單例模式下),這樣雖然實現了執行緒安全的保證,但是由於該方法中操作了兩個物件sysLogDataList和apiLogDataList,並且兩個物件肯定不會被同時操作,這樣就會導致其它不涉及到操作同一物件的執行緒也會處於等待狀態,造成阻塞,降低程式效率,因此將程式碼進行優化成下面部分
public static int cleanDate(int type) { if (type == 0) { synchronized (sysLogDataList) { sysThread.exit = false; int num = httpPost(sysLogDataList); sysLogDataList = Collections.synchronizedList(new ArrayList<>()); dataMap = new HashMap<>(); return num; } } else { synchronized (apiLogDataList) { apiThread.exit = false; int num = httpPost(apiLogDataList); apiLogDataList = Collections.synchronizedList(new ArrayList<>()); return num; } } }
這樣只有在操作該物件時才會被鎖,操作其它物件依然可以進入該方法,這就是降低鎖粒度。
舉個簡單的例子,去KTV唱歌時我們都會關包間的房門,防止其他人打擾,但是我們沒必要將整個KTV鎖住,導致其它顧客不能正常去其它包間,導致資源浪費