前言
工作中自己實現了一個MySessionContext
類,在實現addSession
方法的時候,考慮到會有執行緒不安全問題,這裡需要使用synchronized
關鍵字來保護執行緒安全。
理解 synchronized
關鍵字需要了解多執行緒和執行緒安全的基本概念。在多執行緒環境中,多個執行緒可以同時訪問共享資源(例如記憶體中的變數或物件)。如果這些訪問沒有正確同步,就可能導致資料不一致和其他問題。
多執行緒與執行緒安全
多執行緒:在一個程式中同時執行多個執行緒,每個執行緒執行不同的任務。
執行緒安全:指多個執行緒訪問共享資源時,保證資源的完整性和一致性。
執行緒不安全問題
假設有一個共享資源 sessionMap
(一個 Map<String, HttpSession>
物件),多個執行緒同時向這個 Map 新增會話物件。如果沒有同步機制,可能會出現以下問題:
- 資料不一致:多個執行緒同時寫入 sessionMap,可能導致某些寫操作丟失或覆蓋其他寫操作。
- 競爭條件:多個執行緒競爭訪問同一個資源,導致程式行為不可預測。
- 空指標異常:如果一個執行緒在另一個執行緒完成寫入之前讀取資料,可能會得到不完整或錯誤的資料。
synchronized 關鍵字
Synchronized
關鍵字提供了一種機制,確保在同一時刻只有一個執行緒可以執行同步程式碼塊,從而避免上述問題。
例子:執行緒不安全的程式碼
public void addSession(HttpSession session) {
if (session != null) {
sessionMap.put(session.getId(), session);
}
}
在這個例子中,如果多個執行緒同時呼叫 addSession
方法,可能會同時執行 sessionMap.put()
操作,導致資料不一致。
例子:使用 synchronized
關鍵字確保執行緒安全
public synchronized void addSession(HttpSession session) {
if (session != null) {
sessionMap.put(session.getId(), session);
}
}
使用 synchronized
關鍵字可以確保同一時間只有一個執行緒可以執行 addSession
方法,避免競爭條件和資料不一致的問題。
詳細解釋 synchronized 的作用
同步方法:在方法定義上使用 synchronized
關鍵字,如 public synchronized void addSession(HttpSession session)
,確保同一時間只有一個執行緒可以執行這個方法。
同步塊:你也可以使用同步塊來保護共享資源。
public void addSession(HttpSession session) {
if (session != null) {
synchronized(this) {
sessionMap.put(session.getId(), session);
}
}
}
synchronized 的執行機制
當一個執行緒進入 synchronized
方法或同步塊時,它會獲得該方法或塊對應物件的鎖(monitor)。
其他執行緒必須等待,直到當前執行緒釋放鎖之後,才能進入該同步方法或同步塊。
這樣可以確保同一時間只有一個執行緒訪問被保護的程式碼塊,從而保證執行緒安全。
小結
使用 synchronized
關鍵字,可以確保同一時刻只有一個執行緒執行特定的方法或程式碼塊。這種機制透過鎖(monitor)來實現,防止多個執行緒同時訪問共享資源,從而避免資料不一致和其他執行緒安全問題。