在一個windows服務項目(C#.Net平臺)中,我需要一個建議。
在這個項目中我有一個名爲Cache的類,其中我保留了一些我經常需要的數據。有一個線程在每30分鐘後更新緩存。在哪裏有多個線程使用緩存數據。
在緩存類中,分別有用戶線程和緩存更新程序線程使用的getter和setter函數。沒有人直接使用數據對象,因爲它們是私有成員。
從上面的上下文中,你認爲我應該在緩存類中使用鎖定功能嗎?我應該在多線程範例中鎖定數據表嗎?
回答
寫入共享內存位置(如緩存)時未使用鎖定的效果實際上取決於應用程序。如果代碼被用於銀行軟件,結果可能是災難性的。通常,拇指 - 當多個線程訪問相同的位置時,即使只有一個寫入寫入,另一個讀取,您應該使用鎖定(用於寫入操作)。可能發生的情況是一個線程將開始讀取數據,被更新程序線程刷新;所以它最終可能會使用新舊數據的混合體。如果這真的是一個影響取決於應用程序,它是多麼明智。
要點:如果您不鎖定讀取,您的閱讀將不會看到更改。鎖會強制讀取代碼從主存儲器獲取值,而不是從緩存或寄存器中提取數據。爲了避免真正的鎖定,你可以使用Thread.MemoryBarrier(),它可以完成同樣的工作,而不需要實際鎖定任何東西。
小問題:使用鎖定會阻止讀取半舊數據和半新數據。如果你正在閱讀不止一個領域,我推薦它。如果你真的很聰明,你可以將所有數據保存在一個不可變的對象中,並將該對象返回給調用getter的任何人,因此避免需要鎖定。 (當新數據進入時,你創建一個新的不可變對象,然後用新的替換舊的。如果你仍然感覺真的很聰明,使用實際寫入鎖,或,使字段引用對象易變。)
另外:當你的getter被調用時,記住它在許多其他線程上運行。有一種傾向認爲,一旦有什麼東西在運行緩存類的代碼,它全部在同一個線程上,並且它是而不是。
你有什麼建議是否應該在緩存對象中更新它時鎖定緩存對象,或者在getter中讀取它?我認爲鎖定二傳手會更好! –
@NadeemJamali:都!我的回答集中在閱讀問題上;我只是假設寫鎖是必要的。這裏可能有避免鎖定的方法,但是你必須做其他事情(像不可變對象和易失性字段),並且你必須知道你在做什麼。我試圖做的關鍵點是,不鎖定你的閱讀,特別是如果它們發生在寫作的幾秒鐘內,可能根本看不到所做的更改。他們可能只會看到來自幾次更新的更改,甚至根本沒有更新。 – RalphChapin
- 1. 我可以在Rails中鎖定表嗎? (我應該嗎?)
- 2. 多線程 - 我需要鎖定讀取數據嗎?
- 3. 我應該使用表鎖,而插入數據使用多線程SqlBulkCopy
- 4. 我應該在dlopen之前鎖定嗎?
- 5. 我應該鎖定'事件'嗎?
- 6. 數組上的多線程/我需要鎖定機制嗎?
- 7. 鎖定多線程
- 8. 什麼時候應該在多線程編程中使用「鎖定」?
- 9. 多線程時,我是否必須鎖定數據庫連接?
- 10. 如何在android中鎖定多個線程的數據庫?
- 11. 我應該使用多對多數據庫表的索引嗎?
- 12. 我應該在UI線程中調用`Service`的函數嗎?
- 13. 數據庫規範化 - 我應該將表連接到多深?
- 14. 該數據庫表應該規範化嗎?
- 15. 在多線程中鎖定對象
- 16. 共享對象和多線程問題。我應該在乎嗎?
- 17. Java:我應該在這種情況下使用多線程嗎?
- 18. 我應該使用MySQL的自定義'鎖'表嗎?
- 19. 調用UI線程的多個線程:表單數據需要鎖定?
- 20. 我應該使用多線程嗎? (從API檢索海量數據)
- 21. 我應該如何從數據庫表中實現多線程隊列?
- 22. 我該如何返回範圍鎖定?
- 23. 多線程應用程序中的SQLite「數據庫已鎖定」錯誤
- 24. 鎖定和解鎖多線程應用程序
- 25. 鎖定多個線程
- 26. C#多線程 - 鎖定
- 27. 我可以鎖定當前線程的SQLite表嗎?
- 28. 多線程。 MyLock.acquire(),應該在哪裏放置鎖?
- 29. 數據庫鎖Sqlite多線程
- 30. 多線程應用程序死鎖問題與數據庫
是單身人士的緩存嗎?有更高優先級的線程嗎? – Pandrei
是的,緩存是單身人士。 –
旁註 - 存在用於執行完全相同的緩存的庫,例如Microsoft Enterprise Library。爲什麼重新發明輪子? –