簡體   English   中英

Interlocked.Exchange的安全性如何?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM