這段時間寫程序時,遇到一個問題,當多線程訪問某一個方法時,用synchronized保持同步並沒有起作用,反覆查了資料後,決定用ReentrantLock來替代synchronized,就解決了。原因是synchronized是對象鎖,也就是說多線程創建同一個對象去調用該方法,用synchronized是起作用的,然而當多個線程通過多個對象去調用該方法時則線程不安全。
解決方案,一個static的ReentrantLock ,在方法執行前加鎖,方法執行後解鎖,那麼此方法就線程安全了。
貼一段代碼:
@Override
public HandleStatus prepare() {
try {
lock.lock();
HandleStatus status = super.prepare();
if (!springInited) {// boolean變量得目的是讓static變量只初始化一次,但是prepare是每次都調用的
if(HandleStatus.isSuccess(status)){
initAndroidMobileMap();
initIosMobileMap();
initWpMobileMap();
status = HandleStatus.getSuccessOrFail(Utils.isNotEmpty(androidMobileMap,iosMobileMap,wpMobileMap));
}
springInited = true;
if(!HandleStatus.isSuccess(status))
logger.error(Utils.toLog("MobileChanger初始化失敗"));
}
return status;
} finally {
lock.unlock();
}
}
ReentrantLock 和 synchronized 有一點明顯的區別 —— lock 必須在 finally 塊中釋放。否則,如果受保護的代碼將拋出異常,鎖就有可能永遠得不到釋放!這一點區別看起來可能沒什麼,但是實際上,它極爲重要。忘記在 finally 塊中釋放鎖,可能會在程序中留下一個定時炸彈,當有一天炸彈爆炸時,您要花費很大力氣纔有找到源頭在哪。而使用同步,JVM 將確保鎖會獲得自動釋放。