2013-11-26 23 views
0

在一個windows服務項目(C#.Net平臺)中,我需要一個建議。
在這個項目中我有一個名爲Cache的類,其中我保留了一些我經常需要的數據。有一個線程在每30分鐘後更新緩存。在哪裏有多個線程使用緩存數據。
在緩存類中,分別有用戶線程和緩存更新程序線程使用的getter和setter函數。沒有人直接使用數據對象,因爲它們是私有成員。
從上面的上下文中,你認爲我應該在緩存類中使用鎖定功能嗎?我應該在多線程範例中鎖定數據表嗎?

+0

是單身人士的緩存嗎?有更高優先級的線程嗎? – Pandrei

+0

是的,緩存是單身人士。 –

+0

旁註 - 存在用於執行完全相同的緩存的庫,例如Microsoft Enterprise Library。爲什麼重新發明輪子? –

回答

1

寫入共享內存位置(如緩存)時未使用鎖定的效果實際上取決於應用程序。如果代碼被用於銀行軟件,結果可能是災難性的。通常,拇指 - 當多個線程訪問相同的位置時,即使只有一個寫入寫入,另一個讀取,您應該使用鎖定(用於寫入操作)。可能發生的情況是一個線程將開始讀取數據,被更新程序線程刷新;所以它最終可能會使用新舊數據的混合體。如果這真的是一個影響取決於應用程序,它是多麼明智。

1

要點:如果您不鎖定讀取,您的閱讀將不會看到更改。鎖會強制讀取代碼從主存儲器獲取值,而不是從緩存或寄存器中提取數據。爲了避免真正的鎖定,你可以使用Thread.MemoryBarrier(),它可以完成同樣的工作,而不需要實際鎖定任何東西。

小問題:使用鎖定會阻止讀取半舊數據和半新數據。如果你正在閱讀不止一個領域,我推薦它。如果你真的很聰明,你可以將所有數據保存在一個不可變的對象中,並將該對象返回給調用getter的任何人,因此避免需要鎖定。 (當新數據進入時,你創建一個新的不可變對象,然後用新的替換舊的。如果你仍然感覺真的很聰明,使用實際寫入鎖,,使字段引用對象易變。)

另外:當你的getter被調用時,記住它在許多其他線程上運行。有一種傾向認爲,一旦有什麼東西在運行緩存類的代碼,它全部在同一個線程上,並且它是而不是

+0

你有什麼建議是否應該在緩存對象中更新它時鎖定緩存對象,或者在getter中讀取它?我認爲鎖定二傳手會更好! –

+0

@NadeemJamali:都!我的回答集中在閱讀問題上;我只是假設寫鎖是必要的。這裏可能有避免鎖定的方法,但是你必須做其他事情(像不可變對象和易失性字段),並且你必須知道你在做什麼。我試圖做的關鍵點是,不鎖定你的閱讀,特別是如果它們發生在寫作的幾秒鐘內,可能根本看不到所做的更改。他們可能只會看到來自幾次更新的更改,甚至根本沒有更新。 – RalphChapin

相關問題