这是一个正确的使用Thread.MemoryBarrier的()? [英] Is this a correct use of Thread.MemoryBarrier()?

查看:245
本文介绍了这是一个正确的使用Thread.MemoryBarrier的()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个控制的执行一些循环的领域:

 私有静态布尔shouldRun = TRUE;
 

和我有一个线程在运行,有code这样的:

 而(shouldRun)
{
    //做一些工作....
    Thread.MemoryBarrier();
}
 

现在,另一个线程可以设置 shouldRun ,不使用任何同步机制。

据我了解Thread.MemoryBarrier(),有此调用whil​​e循环中将会prevent我的工作线程获取的缓存版本的 shouldRun ,切实$ P $的发生pventing一个无限循环。

我的理解有关Thread.MemoryBarrier是否正确?由于我有线程,可以设置 shouldRun 变量(这个不能轻易改变),这是一个合理的方式,以确保 shouldRun 设置为false任何线程我的循环将停止一次?

解决方案
  

这是一个正确的使用Thread.MemoryBarrier的()?

没有。假设一个线程之前的循环,甚至开始执行设置标志的。循环仍然可以执行一次,使用标志的缓存值。是的正确的?这当然看起来不正确我。我希望,如果我设置标志循环的第一次执行之前,该循环执行零次,一次也没有。

  

据我了解Thread.MemoryBarrier(),有此调用whil​​e循环中将会prevent我的工作线程得到shouldRun的缓存版本,切实$ P $的发生pventing一个无限循环。我的理解有关Thread.MemoryBarrier是否正确?

的存储器屏障将确保的处理器的不读取和前的写入,使得存储器访问了一个逻辑上的做任何reorderings阻挡实际观察到的的它,反之亦然。

如果你是做小锁code一意孤行,我会倾向于让现场挥发,而不是引入一个明确的内存屏障。 动荡的的C#语言的一个特征。一个危险的和知之甚少的功能,但语言的一个特征。它清楚地传达到的code表示有关字段被去没有在多个线程的锁中使用的读者。

  

这是一个合理的方法,以确保我的循环将停止一旦shouldRun设置为false任何线程?

有些人会认为这是合理的。没有一个非常,非常充分的理由在自己的code我不会这么做。

通常低锁技术由性能方面的考虑有道理的。有这样两个方面的考虑:

首先,主张锁可能是极其缓慢;它块只要有code执行在锁。如果您有性能问题,因为有太多的争议,那么我会首先尝试通过减少竞争来解决问题。只有当我不能消除竞争,我会去到一个低锁技术。

其次,它可能是一个的无竞争的锁太慢。如果作品你在做循环发生,比如,小于200纳秒,然后检查无竞争锁定所需的时间 - 大约20纳秒 - 是的时间显著一部分花在工作。在这种情况下,我建议你的每个循环做更多的工作的。是不是真的有必要环路内200纳秒的控制标志被设置阻止?

只有在最极端的性能场景我可以想象检查的非竞争锁的成本是在程序中花费的时间显著部分。

和也,当然,如果你是诱发记忆障碍每200纳秒左右,你也可能冲倒在其他方面的表现。该处理器的希望的,使这些移动存储器 - 访问 - 围绕在实时优化你;如果你是迫使它不断地抛弃那些优化,你就错过了一个潜在的胜利。

Assume I have a field that controls execution of some loop:

private static bool shouldRun = true;

And I have a thread running, that has code like:

while(shouldRun) 
{
    // Do some work ....
    Thread.MemoryBarrier();
}

Now, another thread might set shouldRun to false, without using any synchronization mechanism.

As far as I understand Thread.MemoryBarrier(), having this call inside the while loop will prevent my work thread from getting a cached version of the shouldRun, and effectively preventing an infinite loop from happening.

Is my understanding about Thread.MemoryBarrier correct ? Given I have threads that can set the shouldRun variable (this can't easily be changed), is this a reasonable way to ensure that my loop will stop once shouldRun is set to false by any thread ?

解决方案

Is this a correct use of Thread.MemoryBarrier()?

No. Suppose one thread sets the flag before the loop even begins to execute. The loop could still execute once, using a cached value of the flag. Is that correct? It certainly seems incorrect to me. I would expect that if I set the flag before the first execution of the loop, that the loop executes zero times, not once.

As far as I understand Thread.MemoryBarrier(), having this call inside the while loop will prevent my work thread from getting a cached version of the shouldRun, and effectively preventing an infinite loop from happening. Is my understanding about Thread.MemoryBarrier correct?

The memory barrier will ensure that the processor does not do any reorderings of reads and writes such that a memory access that is logically before the barrier is actually observed to be after it, and vice versa.

If you are hell bent on doing low-lock code, I would be inclined to make the field volatile rather than introducing an explicit memory barrier. "volatile" is a feature of the C# language. A dangerous and poorly understood feature, but a feature of the language. It clearly communicates to the reader of the code that the field in question is going to be used without locks on multiple threads.

is this a reasonable way to ensure that my loop will stop once shouldRun is set to false by any thread?

Some people would consider it reasonable. I would not do this in my own code without a very, very good reason.

Typically low-lock techniques are justified by performance considerations. There are two such considerations:

First, a contended lock is potentially extremely slow; it blocks as long as there is code executing in the lock. If you have a performance problem because there is too much contention then I would first try to solve the problem by eliminating the contention. Only if I could not eliminate the contention would I go to a low-lock technique.

Second, it might be that an uncontended lock is too slow. If the "work" you are doing in the loop takes, say, less that 200 nanoseconds then the time required to check the uncontended lock -- about 20 ns -- is a significant fraction of the time spent doing work. In that case I would suggest that you do more work per loop. Is it really necessary that the loop stops within 200 ns of the control flag being set?

Only in the most extreme of performance scenarios would I imagine that the cost of checking an uncontended lock is a significant fraction of the time spent in the program.

And also, of course, if you are inducing a memory barrier every 200 ns or so, you are also possibly wrecking performance in other ways. The processor wants to make those moving-memory-accesses-around-in-time optimizations for you; if you are forcing it to constantly abandon those optimizations, you're missing out on a potential win.

这篇关于这是一个正确的使用Thread.MemoryBarrier的()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆