簡體   English   中英

C#(。NET,Mono)使用數組在線程之間傳輸數據

[英]C# (.NET, Mono) Use array for transfer data between threads

今天,我無意間偶然發現了MemoryBarrier,並意識到我不完全了解帶有RAM的CPU的工作。 搜索並沒有給我明確的答案,所以我決定提出一個新問題。

有兩個數組:

int[] dataStates; //default items value is 0
MyStruct[] data; //MyStruct is a struct with several fields

有兩個線程(ThreadA,ThreadB)

ThreadA執行以下代碼:

data[index] = ... //new value
//change to "1" after setting data
Interlocked.Exchange(ref dataStates[index], 1);

ThreadB代碼:

//wait for "1" in array item and replace to "2"
while(Interlocked.CompareExchange(ref dataStates[index], 2, 1) != 1)
{
     Thread.Sleep(0);
}

//read actual data
var value = data[index];

線程是否有可能會從data [index]中讀取數據並且它們已過時? 用過時這個詞表示從數組接收的數據將與在Interlocked.Exchange調用之前設置的數據不匹配。

通常,我嘗試以最有效的方式在線程之間進行數據傳輸。 是否使用這種方法(不帶鎖)是否合適,或者是否存在更多可接受的方法?

我不知道這是否是解決方案,但據我了解您的樣本,您可以執行以下操作:

var queue = new ConcurrentQueue<DateTime>();
var tcs = new CancellationTokenSource();
var token = tcs.Token;
Task.Run(async () => {
    for (var i = 0; i < 2; i++) 
    {
        queue.Enqueue(DateTime.Now);
        await Task.Delay(2000);
    }
    tcs.Cancel();
}, token);
Task.Run(() => {
    while (!token.IsCancellationRequested) 
    {
        if (queue.Any())
        {
            DateTime result;
            queue.TryDequeue(out result);
            Console.WriteLine($"Received {result}...");
        }
    }
}, token).ContinueWith(t =>
{
    Console.WriteLine("Stop");
});
Console.ReadLine();
tcs.Cancel();

您將需要一些名稱空間導入:

using System.Threading;
using System.Threading.Tasks
using System.Collections.Concurrent;

這是一個完全不同的方法,避免了線程之間的手動同步。 我使用DateTime代替MyStruct

從我在對方法ExchangeCompareExchange的引用中所閱讀的內容中,它們並不意味着存在內存障礙。 因此,將值寫入data[index]可以與dataStates[index]的互鎖設置交換,這意味着第二個線程實際上可以讀取無效數據。

我同意sprinter252,可能有更好的方法來實現這一點。 這不是正常的生產者-消費者問題嗎? 這可以通過信號量解決,也可以將其重寫為使用任務隊列,如sprinter的回答。

暫無
暫無

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

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