![](/img/trans.png)
[英]Thread safe generic alternative to Interlocked.Exchange and Interlocked.Exchange global struct support
[英]How safe are Interlocked.Exchange?
Beeing一個線程菜鳥,我正試圖找到一種不用鎖定對象的方法,允許我將線程池任務排入隊列,使其具有最大並行度= 1。
這段代碼會做我認為的嗎?
private int status;
private const int Idle = 0;
private const int Busy = 1;
private void Schedule()
{
// only schedule if we idle
// we become busy and get the old value to compare with
// in an atomic way (?)
if (Interlocked.Exchange(ref status, Busy) == Idle)
{
ThreadPool.QueueUserWorkItem(Run);
}
}
也就是說,如果狀態為Idle
,則以線程安全的方式將Run
方法排入隊列。 它似乎在我的測試中工作正常,但由於這不是我的領域,我不確定。
是的,這將做你想要的。 當實際狀態為Busy時,它永遠不會允許您獲得Idle的返回值,並且它將在同一操作中將狀態設置為Busy,不會發生沖突。 到現在為止還挺好。
但是,如果您稍后使用ConcurrentQueue<T>
,為什么還要這樣做呢? 為什么使用ThreadPool一次又一次地運行Run,而不是讓一個線程使用TryDequeue連續從並發隊列中獲取數據?
事實上,有一個專門為此設計的生產者 - 消費者集合, BlockingCollection<T>
。 您的消費者線程只會調用Take
(如果需要,可以使用取消令牌 - 可能是個好主意),並且返回ConcurrentQueue<T>;
或者如果沒有可用的值,則阻塞線程直到有可能采取的措施。 當一些其他線程將一個項目添加到集合時,它將通知盡可能多的消費者,因為它有數據(在您的情況下,不需要任何復雜的,因為您只有一個消費者)。
這意味着您只需要處理啟動和停止單個線程,該線程將運行“無限”循環,這將調用col.Take
,而生產者調用col.Add
。
當然,這假設你有.NET 4.0+可用,但是你可能會這樣做,因為你正在使用ConcurrentQueue<T>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.