[英]Java consistent synchronization
我們在Spring服務中面臨以下問題:在多線程環境中:
我最初的想法是創建一個容器對象,將三個列表作為屬性。
然后,同步將首先在該對象上,然后在三個列表中的每一個上逐個進行。
有些代碼值得千言萬語......所以這里有一個草稿
private class Sync {
final List<Something> a = Collections.synchronizedList(new ArrayList<Something>());
final List<Something> b = Collections.synchronizedList(new ArrayList<Something>());
final List<Something> c = Collections.synchronizedList(new ArrayList<Something>());
}
private Sync _sync = new Sync();
...
void updateRunOnceEveryFiveMinutes() {
final List<Something> newa = new ArrayList<Something>();
final List<Something> newb = new ArrayList<Something>();
final List<Something> newc = new ArrayList<Something>();
...building newa, newb and newc...
synchronized(_sync) {
synchronized(_sync.a) {
_synch.a.clear();
_synch.a.addAll(newa);
}
synchronized(_sync.b) { ...same with newb... }
synchronized(_sync.c) { ...same with newc... }
}
// Next is accessed by clients
public List<Something> getListA() {
return _sync.a;
}
public List<Something> getListB() { ...same with b... }
public List<Something> getListC() { ...same with c... }
問題是,
更新
更改了_sync同步和newa ...構建的順序。
謝謝
你最好的選擇是暴露一個“當前狀態”對象並使用volatile,拋棄所有同步代碼。 (另外,您可能希望使列表不可修改的包裝器只是為了安全)。
public class ListState {
List final a;
List final b;
List final c;
}
private volatile ListState _state;
void updateRunOnceEveryFiveMinutes() {
// generate new lists ...
// re-assign current list state (e.g. atomically publish all your updates)
_state = new ListState(newA, newB, newC);
}
public ListState getCurrentLists() {
return _state;
}
構建新列表只是為了將其復制到另一個(最終)列表中,這有點浪費。
在構建列表之后(在updateRunOnceEveryFiveMinutes
)考慮使用不可變列表並將新列表分配給_sync.a
, _sync.b
和_sync.c
(已從中刪除了final
修飾符)。
您還在同步4個不同的對象。 對於每個方法調用,僅對一個對象( _sync
或可能是專用鎖對象)進行同步會更簡單。
如果getListA
等返回的列表是不可變的,那么您也不需要調用Collections.synchronizedList
。
草案沒有達到你的目標。 這里沒有任何東西阻止在計算新的A或B時訪問舊的C. 實現這一目標的最簡單方法是:
synchronized (a) {
synchronized (b) {
synchronized (c) {
}
}
}
圍繞所有訪問,無論是讀還是寫。 我不會做clear()和addAll(),只需將變量值更改為newA / newB / newC,雖然這需要對上面的內容進行一些調整。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.