這種事情已經完成了一百萬次,但我確信,但我的搜索foo今天看起來很虛弱,我想獲得關於通常被認爲是最佳實現這一目標的方法。鎖定線程間併發數據庫記錄
我的應用程序會跟蹤系統中在線用戶的會話。每個會話對應於數據庫中的單個記錄。會話可以通過以下兩種方式之一結束。收到「停止」消息,或會話可能超時。前一種情況很簡單,它在消息處理線程中處理,一切都很好。後一種情況是關注點來自哪裏。
爲了處理超時,每條記錄都有一個結束時間列,每次收到該會話的消息時都會更新一次。爲了使超時工作,我有一個線程返回NOW()(結束時間爲過去)的數據庫中的所有記錄,並通過處理關閉這些會話。這裏的問題是,當超時線程正在處理同一會話時,可能會收到會話消息。我最終在超時線程和消息處理線程之間進行競爭。
我可以使用一個信號燈或類似的東西,只是防止消息線程在超時發生時處理,因爲它只需要每30秒或一分鐘運行一次。但是,隨着用戶表變大,這將會遇到一些嚴重的性能問題。我想我想知道的方法是在消息線程中知道此記錄目前正在由超時線程處理。如果我能夠實現這一點,我可以放棄該消息或等待超時線程結束,但僅在衝突現在而不是總是衝突的情況下。
目前我的應用程序直接使用JDBC。如果我使用Hibernate這樣的框架,會不會有更簡單/標準的方法來解決這個問題?
您可以通過會話ID而不是線程級別來包裝信號量,因此您已在消息處理程序和超時線程的關閉部分中同步(sessionID)塊。我認爲它不像你想要的那麼幹淨,但是它比將整個線程鎖定在單個信號量上的性能影響更小,因爲只有該會話的消息纔會被阻塞。 – Thomas 2012-02-06 16:24:18
這將如何工作?我的理解是,這將鎖定* object * sessionID,而不是sessionID的*值*。由於在數據庫讀取之後在兩個線程中創建的對象不是同一個對象,所以它看起來好像永遠不會阻塞。如果您有一個鎖對象的字段並在同步塊之前從兩個線程更新它,則您擁有與之前的併發性相同的問題,只需將焦點切換到鎖對象即可。除非有一種方法可以同步我不知道的*值*上的塊。 – tdimmig 2012-02-06 21:51:13
答案根據你的結構而改變。如果你有mysession.handleMessage(x)和mysession.closeAndCleanup(),你應該可以鎖定mysession。然後競爭條件是,如果在會話被標記爲關閉之後但在到達同步塊之前接收到消息,則將處理消息並關閉會話或關閉會話,並且消息將返回關於超時的錯誤。如果結構是handlemessage(ID,msg)和close(ID),其中ID只是一個int,那麼您需要一個Map或其他東西來同步。 – Thomas 2012-02-07 15:53:12