3 回答

TA貢獻1876條經(jīng)驗 獲得超5個贊
我們讓instrumentList實例以非同步方式逃逸,即訪問/操作在列表上發(fā)生而沒有任何同步。通過將副本傳遞給其他方法來修復相同的問題就可以了。
以下代碼行是發(fā)生此問題的代碼行
recordSaver.persist(instrumentList); 儀器列表.clear();
在這里,我們允許instrumentList實例以非同步方式逃逸,即它被傳遞到另一個類(recordSaver.persist),在該類中對其進行操作,但我們也在下一行(在 Aggregator 類中)清除列表,并且所有這些都以非同步方式發(fā)生。無法在記錄保護程序中預測列表狀態(tài)......一個非常愚蠢的錯誤。
我們通過將instrumentList的克隆副本傳遞給 recordSaver.persist(...) 方法來解決此問題。這樣,instrumentList.clear()不會影響 recordSaver 中可用的列表以進行進一步操作。

TA貢獻1788條經(jīng)驗 獲得超4個贊
看起來這是對不需要的優(yōu)化的嘗試。在這種情況下,越少越好,越簡單越好。在下面的代碼中,僅使用了兩個并發(fā)概念:synchronized確保正確更新共享列表并final確保所有線程看到相同的值。
import java.util.ArrayList;
import java.util.List;
public class Aggregator<T> implements Runnable {
private final List<T> instruments = new ArrayList<>();
private final RecordSaver recordSaver;
private final int batchSize;
public Aggregator(RecordSaver recordSaver, int batchSize) {
super();
this.recordSaver = recordSaver;
this.batchSize = batchSize;
}
public synchronized void addAll(List<T> moreInstruments) {
instruments.addAll(moreInstruments);
if (instruments.size() >= batchSize) {
storeInstruments();
}
}
public synchronized void storeInstruments() {
if (instruments.size() > 0) {
// in case recordSaver works async
// recordSaver.persist(new ArrayList<T>(instruments));
// else just:
recordSaver.persist(instruments);
instruments.clear();
}
}
@Override
public void run() {
while (true) {
try { Thread.sleep(1L); } catch (Exception ignored) {
break;
}
storeInstruments();
}
}
class RecordSaver {
void persist(List<?> l) {}
}
}

TA貢獻1802條經(jīng)驗 獲得超4個贊
我明白了,您parallelStream
在鎖中使用了 ConcurrentHashMap。我不了解 Java 8+ 流支持,但快速搜索顯示,
ConcurrentHashMap 是一種復雜的數(shù)據(jù)結(jié)構(gòu),過去曾經(jīng)存在并發(fā)錯誤
并行流必須遵守復雜且記錄不充分的使用限制
您正在并行流中修改數(shù)據(jù)
基于這些信息(以及我的直覺驅(qū)動的并發(fā)錯誤檢測器?),我敢打賭,刪除對的調(diào)用parallelStream
可能會提高代碼的健壯性。此外,正如@Slaw 所提到的,如果所有instrumentMap
使用都已被鎖保護,則應該使用普通 HashMap 代替 ConcurrentHashMap 。
當然,由于您沒有發(fā)布 的代碼recordSaver
,因此它也有可能存在錯誤(不一定是與并發(fā)相關(guān)的錯誤)。特別是,您應該確保從持久存儲中讀取記錄的代碼(用于檢測記錄丟失的代碼)是安全、正確的,并且與系統(tǒng)的其余部分正確同步(最好使用健壯的, 行業(yè)標準的 SQL 數(shù)據(jù)庫)。
添加回答
舉報