相关疑难解决方法(0)

读取由Interlocked在其他线程上更新的int

(这是重复:如何正确读取Interlocked.Increment'ed int字段?但是,在阅读了答案和评论之后,我仍然不确定正确的答案.)

有些代码我不拥有,也无法更改为使用在几个不同线程中增加int计数器(numberOfUpdates)的锁.所有通话都使用:

Interlocked.Increment(ref numberOfUpdates);
Run Code Online (Sandbox Code Playgroud)

我想在我的代码中读取numberOfUpdates.既然这是一个int,我知道它不会撕裂.但是,确保我获得最新价值的最佳方法是什么?看起来我的选择是:

int localNumberOfUpdates = Interlocked.CompareExchange(ref numberOfUpdates, 0, 0);
Run Code Online (Sandbox Code Playgroud)

要么

int localNumberOfUpdates = Thread.VolatileRead(numberOfUpdates);
Run Code Online (Sandbox Code Playgroud)

两者都有效(无论优化,重新排序,缓存等,都可以提供最新的价值)?一个比另一个更受欢迎吗?还有第三种选择更好吗?

.net c# multithreading interlocked interlocked-increment

35
推荐指数
3
解决办法
1万
查看次数

如何为Unity3D编写线程安全的C#代码?

我想了解如何编写线程安全代码.

例如,我在我的游戏中有这个代码:

bool _done = false;
Thread _thread;

// main game update loop
Update()
{
    // if computation done handle it then start again
    if(_done)
    {
        // .. handle it ...
        _done = false;
        _thread = new Thread(Work);
        _thread.Start();
    }
}

void Work()
{
     // ... massive computation

     _done = true;
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,可能会发生主游戏线程和我_thread可以拥有自己的缓存版本_done,并且一个线程可能永远不会_done在另一个线程中看到更改?

如果可能,如何解决?

  1. 是否可以解决,只应用volatile关键字.

  2. 或者是有可能读取和写入,通过价值Interlocked的类似的方法ExchangeRead

  3. 如果我包围_done读写操作lock (_someObject),需要我使用Interlocked什么东西来防止缓存?

编辑1

  1. 如果我定义 …

c# multithreading unity-game-engine

23
推荐指数
4
解决办法
6904
查看次数

Interlocked.Exchange和Volatile.Write之间的区别?

Interlocked.Exchange和Volatile.Write有什么区别?

两种方法都更新某些变量的值.有人可以总结何时使用它们?

http://msdn.microsoft.com/ru-ru/library/bb337971http://msdn.microsoft.com/en-us/library/gg712713.aspx

特别是我需要更新我的数组的双项,我希望另一个线程看到最新的值.什么是首选?Interlocked.Exchange(ref arr[3], myValue)Volatile.Write(ref arr[3], info);在那里arr被声明为double

================================================== ==========================真实的例子,我声明了这样的双数组:

private double[] _cachedProduct;
Run Code Online (Sandbox Code Playgroud)

在一个线程中,我更新它:

        _cachedProduct[instrumentId] = calcValue;
        ...
        are.Set();
Run Code Online (Sandbox Code Playgroud)

在另一个线程中,我像这样读取这个数组:

        while(true) {
            are.WaitOne();
            ...
                result += _cachedProduct[instrumentId];
            ...
        }
Run Code Online (Sandbox Code Playgroud)

对我来说它只是工作正常.然而,为了确保"它将永远有效",无论它看起来我应该添加Volatile.WriteInterlocked.Exchange.因为双重更新不能保证是原子的http://msdn.microsoft.com/en-us/library/aa691278%28VS.71%29.aspx

在这个问题的答案中,我希望看到Volatile和Interlocked类的详细比较.为什么我们需要2节课?哪一个和何时使用?

c# .net-4.5

21
推荐指数
2
解决办法
3387
查看次数

.NET中的可变新鲜度保证(易失性与易失性读取)

我读过很多关于volatile和VoletileRead(ReadAcquireFence)的矛盾信息(msdn,SO等).

我理解那些内存访问重新排序的限制含义 - 我仍然完全混淆的是新鲜度保证 - 这对我来说非常重要.

msdn doc for volatile提及:

(...)这可确保始终在字段中显示最新值.

用于volatile字段的msdn doc提及:

读取volatile字段称为volatile读取.易失性读取具有"获取语义"; 也就是说,保证在指令序列之后发生的任何内存引用之前发生.

VolatileRead的.NET代码是:

public static int VolatileRead(ref int address)
{
    int ret = address;
    MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

根据msdn MemoryBarrier doc内存屏障阻止重新排序.然而,这似乎对新鲜度没有任何影响 - 对吗?

如何获得新鲜度保证?标记字段volatile与使用VolatileRead和VolatileWrite语义访问它之间有区别吗?我目前正在执行我的性能关键代码,需要保证新鲜度,但读者有时会得到陈旧的价值.我想知道是否标记状态不稳定将使情况不同.

EDIT1:

我正在努力实现的目标 - 保证读者线程将尽可能获得共享变量(由多个编写者编写)的最新值 - 理想情况下不会超过上下文切换或其他可能推迟立即操作的操作的成本写国家.

如果挥发性或更高级别的构造(例如锁定)具有这种保证(是吗?)而不是它们如何实现这一点?

EDIT2:

非常简洁的问题应该是 - 如何在读取过程中尽可能保证新的价值?理想情况下没有锁定(因为不需要独占访问,并且存在高争用的可能性).

从我在这里学到的东西,我想知道这可能是解决方案(求解(?)行标有注释):

private SharedState _sharedState;
private SpinLock _spinLock = new SpinLock(false);

public void Update(SharedState newValue) …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading volatile memory-barriers

17
推荐指数
1
解决办法
2007
查看次数

如何保证对Array中"reference type"项的更新对其他线程可见?

private InstrumentInfo[] instrumentInfos = new InstrumentInfo[Constants.MAX_INSTRUMENTS_NUMBER_IN_SYSTEM];

public void SetInstrumentInfo(Instrument instrument, InstrumentInfo info)
{
    if (instrument == null || info == null)
    {
        return;
    }
    instrumentInfos[instrument.Id] = info;  // need to make it visible to other threads!
}

public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
    return instrumentInfos[instrument.Id];  // need to obtain fresh value!
}
Run Code Online (Sandbox Code Playgroud)

SetInstrumentInfoGetInstrumentInfo从不同的线程调用. InstrumentInfo是不可变的类.我保证在打电话时有最新的副本GetInstrumentInfo吗?我担心我可以收到"缓存"副本.我应该添加同步吗?

声明instrumentInfosvolatile不会帮助,因为我需要声明数组项为volatile,不是数组本身.

我的代码有问题,如果有问题如何解决?

UPD1:

我需要我的代码在现实生活中工作,不符合所有规范!因此,如果我的代码在现实生活中起作用,但在某些环境下的某些计算机上"理论上"不起作用 - 那没关系!

  • 我需要我的代码在Windows下使用最新的.NET Framework在现代X64服务器(目前有2个处理器HP DL360p Gen8)上工作.
  • 我不需要在奇怪的计算机或Mono或其他任何东西下使用我的代码
  • 我不想引入延迟,因为这是HFT软件.因此,"微软的实现使用强大的内存模型进行写入.这意味着写入被视为易失性"我可能不需要添加额外的内容Thread.MemoryBarrier,除了增加延迟之外什么都不做.我认为我们可以相信微软将在未来版本中继续使用"强大的内存模型".至少微软不太可能改变内存模型.所以我们假设它不会.

UPD2: …

c# multithreading synchronization volatile

10
推荐指数
1
解决办法
1139
查看次数

报告线程进度的最佳方式

我有一个程序,它使用线程顺序执行耗时的进程.我希望能够监视每个线程的进度,类似于BackgroundWorker.ReportProgress/ ProgressChangedmodel的方式.我不能使用ThreadPoolBackgroundWorker由于我的其他限制.允许/公开此功能的最佳方法是什么.重载Thread该类并添加属性/事件?另一个更优雅的解决方案?

c# multithreading backgroundworker threadpool

6
推荐指数
1
解决办法
1万
查看次数