2013-07-12 24 views
0

我有一個作家和一個concurrentbag的多個讀者。重新初始化concurent包是否安全?

作者定期刷新數據庫中concurrentbag的完整內容。

在編寫器線程中重新初始化(ie = new concurrentbag)是否安全?如果沒有,我認爲唯一的選擇就是在所有的讀寫操作中鎖定它,這相當重要。我無法一次遍歷整個包以將其清空,因爲任何讀取該進程的糞便都會將其行爲建立在部分信息之上。

謝謝大家!

+1

你有什麼擔心?某些讀者線程可能會在ConcurrentBag <>'的一個實例上啓動讀取操作,然後在另一個實例上完成相同的讀取操作?或者你是否擔心該線程不會提取新的參考?也許你想要一個'volatile'字段(如果這是一個字段)? –

+0

謝謝你的回覆,Jeppe。我的擔心是重新初始化會在閱讀過程中發生,並且會出現異常。 –

+0

當您這樣做時,您正在更新引用,這在.NET中是原子的。結果當然是隨機的,確切地說,從舊包裏消耗的物品是完全不可預測的。很難看出這可能是可以接受的行爲,但它永遠不會。 –

回答

1

首先,這與ConcurrentBag類型無關。就此而言,它本身就是完全安全的。

如果一個線程被包裝袋上做了一個方法調用,而在同一時間對另一個線程你這樣做:

_BagField = new ConcurrentBag<string>(); 

然後第一個線程調用該方法將完成就好了,但舊實例上的

然而,是不是安全的,但由於原因首先使用類型,從來沒有

if (_BagField.Any()) 
    var percentage = 100/_BagField.Count(); // broken 

這可以稱之爲.Any()一個實例,.Count()上另一個,但這從來沒有安全,因爲沒有任何保障措施可以確保在您撥打Any之後伯爵不會降至零。

但是,請注意,您不能保證其他線程立即拿起新實例。

舉例來說,這樣的:

string temp; 
while (!_Bag.TryTake(out temp)) 
{ 
    // process temp 
} 

可能永遠不會得到新的實例,並會繼續只是停止死亡前處理老包實例。

爲確保確保包含袋參考的字段爲volatile

+0

謝謝Lasse。因此,如果我讓我的concurrentbag變得易變,並且在我的閱讀線程中執行一個副本(例如ToList),然後對該副本進行操作,那麼它將保證是一組完整的數據,因爲它可能在作者之前或之後線程重新初始化它。正確? –

+0

是的,就替換實例而言,這是正確的,但是,我不知道'ToList'和'ConcurrentBag'如何協同工作,因此您可能希望確保'ToList'完全是線程安全的,而不是關於替換整個實例,但是是否會處理另一個線程同時修改包。 –

+0

超級騙子。謝謝! –