簡體   English   中英

使用volatile在.NET中的線程之間進行單向通信

[英]Using volatile for one-way communication between threads in .NET

我已經閱讀了相當多的關於這個主題的帖子,我想我終於明白了volatile關鍵字在C#中是如何工作的。 我仍然想在這里問一下,以確保我理解正確的概念。 請考慮以下代碼:

class ThreadWrapper
{
  public bool Enabled { get; set; }

  private void ThreadMethod()
  {
    while (Enabled) { // ... Do work }
  }
}

根據我的理解,如果另一個線程設置為Enabled=false ,原始線程可能不會立即(或者可能永遠?)看到此更改。 為了確保編譯器不優化對Enabled屬性的訪問並依賴緩存值,更改代碼如下所示應該解決問題。

  public bool Enabled { get {return mEnabled;} set {mEnabled=value;} }
  private volatile bool mEnabled;

現在,只要讀取Enabled值,就可以保證獲得最新值,對嗎? 如果是這樣,我應該能夠將它用作簡單的信號或標志(就像我上面所說的那樣)。

作為另一個例子,請考慮以下事項:

class C
{
  private volatile int i;
  private volatile bool enabledA;
  private volatile bool enabledB;

  void ThreadA()
  {
    i = 0; // Reset counter
    while (enabledA)
    {
      // .. Do some other repeated work
      if (i > 100)
      {
        // .. Handle threshold case
      }
    }
  }

  void ThreadB()
  {
    while (enabledB)
    {
      // .. Do work
      if (condition) // Some condition occurs that we want to count
      {
        i++;
      }
    }
  }
}

對於像這樣簡單的線程間通信,這里的volatile令人滿意嗎? 我知道i++不是一個原子操作,但如果一個線程正在進行所有遞增而另一個只是想讀取它以查看它是否達到某個閾值,我們沒關系嗎?

編輯:我當然在事后發現了另一個類似的問題和詳細的答案

我相信你是對的。

MSDN關於volatile關鍵字的文章在其示例中使用了這種相同的技術。

是的,這應該是安全的,並且是volatile關鍵字的預期用途之一。 但請注意,您不應僅僅為了測試條件而循環; 如果您只想等待它更改,請使用適當的同步原語以避免浪費CPU時間。 另請注意,此技術僅適用,因為您只有一個線程寫入; 如果多個線程嘗試遞增計數器,則可能會丟失計數器命中(因為讀取 - 修改 - 寫入不是原子的)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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