gpt4 book ai didi

c# - 无锁线程安全状态同步?

转载 作者:太空宇宙 更新时间:2023-11-03 21:13:16 25 4
gpt4 key购买 nike

首先,我知道这样的问题:

reference assignment is atomic so why is Interlocked.Exchange(ref Object, Object) needed?

...但我仍然不确定我是否可以在我的案例中避免使用 lock(){}。

在我的例子中,我有一个代表某种状态的类,并且只有一个不时修改该状态的单一线程。虽然有许多线程读取状态。

在我的情况下,状态对象是否需要 Interlocked.Exchange()?我绝对必须使用 lock(){}

这是我的示例代码,已简化为最低限度:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace MultiThreadingExample
{
class State
{
public int X { get; set; }
public string Str { get; set; }
public DateTime Current { get; set; }
}

class Example
{
State state;
CancellationTokenSource cts = new CancellationTokenSource();

Task updater;
List<Task> readers = new List<Task>();

public void Run()
{
updater = Task.Factory.StartNew(() =>
{
while (!cts.Token.IsCancellationRequested)
{
// wait until we have a new state from some source
Thread.Sleep(1000);

var newState = new State() { Current = DateTime.Now, X = DateTime.Now.Millisecond, Str = DateTime.Now.ToString() };

// critical part
state = newState;
}
}, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);

for (int i = 0; i < 10; i++)
{
readers.Add(Task.Factory.StartNew(() =>
{
while (!cts.Token.IsCancellationRequested)
{
// critical part
var readState = state;

// use it
if (readState != null)
{
Console.WriteLine(readState.Current);
Console.WriteLine(readState.Str);
Console.WriteLine(readState.X);
}
}
}, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default));
}
}
}

class Program
{
static void Main(string[] args)
{
new Example().Run();
Console.ReadKey();
}
}
}

最佳答案

有疑问时使用锁

除非您实际上注意到性能问题有一个部分可以被异步逻辑访问,该逻辑可能是也可能不是多线程的并且需要进行等待和发信号会推荐使用锁来实现线程间的同步。

话虽如此

可以使用 Thread.MemoryBarrier 来完成您的要求

只要您不关心所读取数据的准确性,您最终遇到的问题就与编译器优化有关因为它是多线程的,所以错误地重新排序了你的指令。

一种可以避免这种情况的方法是使用 Thread.MemoryBarrier 方法。

            while (!cts.Token.IsCancellationRequested)
{
//No command before the barrier
Thread.MemoryBarrier();
//Can end up on this side of the barrier

// critical part
var readState = state;

// use it
if (readState != null)
{
Console.WriteLine(readState.Current);
Console.WriteLine(readState.Str);
Console.WriteLine(readState.X);
}
}

这叫做半围栏,这里有很多关于围栏的信息,解释得比我以前能解释的要好得多a free ebook, Threading in C# by Joseph Albahari

关于c# - 无锁线程安全状态同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36286192/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com