2011-11-15 25 views
2

我有一個運行多線程的Hibernate事務方法「doImportImpl」。然而某些記錄需要按順序導入,所以代碼結構大致是這樣的:如何在一個方法周圍定義的Java方面進行同步?

public RecordResult doImportImpl(String data) { 
    RecordResult result = new RecordResult(); 
    .. do some data processing .. 
    String recordIdentifier = getIdentifier(data); 
    synchronized(recordIdentifier) { 
     process record; 
    } 
    return result; 
} 

有一個不同的交易的方法,其還具有記錄標識符,並且不能在平行於記錄進口運行。因此它也在「記錄標識符」上同步。

public void autoProcess(String data) { 
    String recordIdentifier = getIdentifier(data); 
    synchronized(recordIdentifier) { 
     List<Record> records = dao.queryDatabase(recordIdentifier); 
     for (Record r : records) { 
      autoprocess record; 
     } 
    } 
} 

這裏的問題:似乎有時是autoProcess()開始從doImportImpl()同步塊之後運行的方法完成,但之前事務被提交。因此,由於tx隔離級別,對dao.queryDatabase()的調用尚未在數據庫中看到導入的記錄。

如何確保同步鎖定一直保持通過「return語句」,包括方法調用(處理Hibernate事務管理)的所有方面?將return語句放入synchronized塊是否足夠?

感謝 西蒙Niederberger

回答

0

你必須使用數據庫鎖,而不是​​塊。當您通過recordIdentifier查詢記錄時,請使用select for update或您的數據庫可用的內容。

另外,對我來說,它的氣味是同步String s。

+0

謝謝你的提示。在字符串上同步。我認爲我已經理解了這些含義,但是在閱讀了一些關於該主題的文章之後被證明是錯誤的。我會改變這一部分,但不管那個主要問題仍然存在。我不願意「選擇更新」,因爲這可能會影響數據庫的性能。 98%的時間沒有對具有相同記錄標識符的數據進行併發處理,所以應該針對該情況優化代碼。 – Simon

+0

然後使用樂觀鎖定。 – kan