[英]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
。
從我在對方法Exchange和CompareExchange的引用中所閱讀的內容中,它們並不意味着存在內存障礙。 因此,將值寫入data[index]
可以與dataStates[index]
的互鎖設置交換,這意味着第二個線程實際上可以讀取無效數據。
我同意sprinter252,可能有更好的方法來實現這一點。 這不是正常的生產者-消費者問題嗎? 這可以通過信號量解決,也可以將其重寫為使用任務隊列,如sprinter的回答。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.