引用赋值是原子那么为什么Interlocked.Exchange(Ref对象,对象)的需要? [英] reference assignment is atomic so why is Interlocked.Exchange(ref Object, Object) needed?

查看:202
本文介绍了引用赋值是原子那么为什么Interlocked.Exchange(Ref对象,对象)的需要?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的多线程ASMX Web服务,我有我自己的类型SystemData的一类领域_allData它由几个列表与LT的; T> 词典< T> 标记为挥发性 newData 并填写系统数据( _allData )将在一段时间刷新一次,我通过创建另一个名为对象,做它与新的数据的数据结构。当它完成我只是分配

In my multithreaded asmx web service I had a class field _allData of my own type SystemData which consists of few List<T> and Dictionary<T> marked as volatile. The system data (_allData) is refreshed once in a while and I do it by creating another object called newData and fill it's data structures with new data. When it's done I just assign

private static volatile SystemData _allData

public static bool LoadAllSystemData()
{
    SystemData newData = new SystemData();
    /* fill newData with up-to-date data*/
     ...
    _allData = newData.
} 

这应该工作,因为分配是原子和具有参考旧数据线程继续使用它,只是分配后剩下的有新的系统数据。但是我collegue说,而不是使用挥发性关键字和简单的assigment我应该使用 InterLocked.Exchange ,因为他说,一些平台上它不保证引用赋值是原子的。另外:当我宣布的_allData 字段挥发性

This should work since the assignment is atomic and the threads that have the reference to old data keep using it and the rest have the new system data just after assignment. However my collegue said that instead of using volatile keyword and simple assigment I should use InterLocked.Exchange because he said that on some platforms it's not guaranteed that reference assignment is atomic. Moreover: when I declare the _allData field as volatile the

Interlocked.Exchange<SystemData>(ref _allData, newData); 

产生警告,以易失性字段的引用将不会被视为动荡我应该考虑这一点?

produces warning "a reference to a volatile field will not be treated as volatile" What should I think about this?

推荐答案

在这里有很多的问题。考虑到他们一次:

There are numerous questions here. Considering them one at a time:

引用赋值是原子那么为什么Interlocked.Exchange(Ref对象,对象)需要的?

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

参考分配是原子。 Interlocked.Exchange没有做仅供参考分配。它变量的当前值的读出,存储起来,旧值,并且新的值分配给变量,所有作为一个原子操作。

Reference assignment is atomic. Interlocked.Exchange does not do only reference assignment. It does a read of the current value of a variable, stashes away the old value, and assigns the new value to the variable, all as an atomic operation.

我的同事说,在一些平台上它不保证引用赋值是原子的。是我的同事纠正?

my colleague said that on some platforms it's not guaranteed that reference assignment is atomic. Was my colleague correct?

没有。参考分配是保证所有的.NET平台上的原子。

No. Reference assignment is guaranteed to be atomic on all .NET platforms.

我的同事从假premises推理。这是否意味着,他们的结论是不正确的?

My colleague is reasoning from false premises. Does that mean that their conclusions are incorrect?

不一定。你的同事可能是给你不好的原因很好的建议。也许有一些其他的原因,你应该使用Interlocked.Exchange。无锁编程是出奇的困难,你从该领域的专家所信奉行之有效的做法,离开的那一刻,你是关中杂草和冒着最恶劣的比赛条件。我既不是在这方面的专家,也没有在你的code的专家,所以我无法做出判断的一种方式或其他。

Not necessarily. Your colleague could be giving you good advice for bad reasons. Perhaps there is some other reason why you ought to be using Interlocked.Exchange. Lock-free programming is insanely difficult and the moment you depart from well-established practices espoused by experts in the field, you are off in the weeds and risking the worst kind of race conditions. I am neither an expert in this field nor an expert on your code, so I cannot make a judgement one way or the other.

产生警告,以易失性字段的引用将不会被视为动荡我应该考虑这一点?

produces warning "a reference to a volatile field will not be treated as volatile" What should I think about this?

您应该明白为什么这是一个问题一般。这将导致为什么警告在这种特殊情况下不重要的理解。

You should understand why this is a problem in general. That will lead to an understanding of why the warning is unimportant in this particular case.

这是编译器为这个警告的原因是因为一个标记字段作为挥发性手段这个领域是怎么回事多个线程进行更新 - 不产生任何code,它缓存此字段的值,并确保任何读取或本领域中写道:无法通过处理器缓存不一致向前和向后移动的时间。

The reason that the compiler gives this warning is because marking a field as volatile means "this field is going to be updated on multiple threads -- do not generate any code that caches values of this field, and make sure that any reads or writes of this field are not "moved forwards and backwards in time" via processor cache inconsistencies."

(我假设你明白这一切了。如果你不具备挥发性的意义有深入的了解和你它如何影响处理器缓存的语义,则无法理解它是如何工作的,不应该被使用的挥发性。锁 - 免费程序都很难得到的权利;确保你的计划是正确的,因为你了解它是如何工作的,不是偶然的右)

(I assume that you understand all that already. If you do not have a detailed understanding of the meaning of volatile and how it impacts processor cache semantics then you don't understand how it works and should not be using volatile. Lock-free programs are very difficult to get right; make sure that your program is right because you understand how it works, not right by accident.)

现在假设你犯了一个变量,它通过将裁判那场挥发性场的别名。内部调用的方法,编译器没有任何理由知道该参考需要有挥发性的语义!编译器将生成乐呵呵code对于不执行挥发性领域规则的方法,但是变量的的挥发性场。这完全可以毁掉你的无锁逻辑;假设始终是一个动荡场的总是的挥发性语义访问。这是没有意义的把它当作挥发性有时而不是其他倍;你要的总是的保持一致,否则,你能不能保证其他访问的一致性。

Now suppose you make a variable which is an alias of a volatile field by passing a ref to that field. Inside the called method, the compiler has no reason whatsoever to know that the reference needs to have volatile semantics! The compiler will cheerfully generate code for the method that fails to implement the rules for volatile fields, but the variable is a volatile field. That can completely wreck your lock-free logic; the assumption is always that a volatile field is always accessed with volatile semantics. It makes no sense to treat it as volatile sometimes and not other times; you have to always be consistent otherwise you cannot guarantee consistency on other accesses.

因此​​,当你这样做的编译器警告,因为它很可能将彻底搞乱你精心研制无锁的逻辑。

Therefore, the compiler warns when you do this, because it is probably going to completely mess up your carefully developed lock-free logic.

当然,Interlocked.Exchange的的书面期待挥发性领域,做正确的事情。该警告是因此误导。我后悔十分;我们应该做的是实现某种机制,使像Interlocked.Exchange方法的作者可以把一个属性的方法,说:这个方法,这需要裁判强制对变量波动语义,SUP preSS警告 。也许在编译器的未来版本中,我们将这样做。

Of course, Interlocked.Exchange is written to expect a volatile field and do the right thing. The warning is therefore misleading. I regret this very much; what we should have done is implement some mechanism whereby an author of a method like Interlocked.Exchange could put an attribute on the method saying "this method which takes a ref enforces volatile semantics on the variable, so suppress the warning". Perhaps in a future version of the compiler we shall do so.

这篇关于引用赋值是原子那么为什么Interlocked.Exchange(Ref对象,对象)的需要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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