不可变对象总是线程安全的吗?
可以安全地假设使用或传递不可变对象始终是线程安全的吗?
It is safe to assume that working with or passing around an immutable object would always be threadsafe?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
是的。如果一个对象确实是不可变的,并且没有发生内部突变,那么该对象本身将是线程安全的。
(是否处理对象并以线程安全的方式传递它是另一回事!)
“内部突变”是什么意思?
许多对象从外部看来是不可变的 - 例如,不属性设置器或其他成员显然会触发突变 - 但这并不意味着对象的私有内部无法更改。
这就是为什么记录对象和/或其成员的可变性和线程安全性很重要。否则,如果不仔细检查内部结构(这是一个实现细节,可能随时更改),对象的使用者就无法发现这一点。
Yes. If an object is truly immutable, with no internal mutations occurring, then the object itself will be threadsafe.
(Whether you handle the object and pass it around in a threadsafe manner is another matter!)
What do I mean by "internal mutations"?
Many objects appear to be immutable from the outside - for example, no property setters or other members that would obviously trigger mutations - but that doesn't mean that the private internals of the object aren't capable of changing.
That's why it's important to document the mutability and thread-safety of your objects and/or their members. Otherwise there's no way for consumers of your object to discover this without closely examining the internals (which are an implementation detail and could change at any time).
这取决于线程安全的含义;作为 Eric Lippert 的博客指出,这个术语可以有多种含义。不可变对象保证无论何时访问给定实例上的属性或方法,结果始终是相同的;这是该实例的线程安全性。但是,如果您有一个包含对不可变对象的引用的可变字段,则通过同一字段的多次调用可能不会针对同一实例,因此不一致(即“线程安全”)。
我怀疑对于您所想到的“线程安全”的含义,答案是肯定的。但请记住,不可变对象并不是万能的。它们不会让您免受线程交互的影响,它们只是提供跨单个实例的一致性。
That depends what you mean by threadsafe; as Eric Lippert's blog points out, the term can mean several things. Immutable objects guarantee that no matter when you access a property or method on a given instance, the result will always be the same; this is thread safety across that instance. However, if you have a mutable field containing a reference to an immutable object then multiple calls via the same field may not be to the same instance, hence are not consistent (i.e. "threadsafe").
I suspect that for the meaning of "threadsafe" that you have in mind, the answer is yes. But keep in mind that immutable objects aren't a golden bullet; they don't make you immune to thread interactions, they just provide consistency across a single instance.
正确回答这个问题:不。
您不能假设不可变对象始终是线程安全的。
但很可能是。另请参阅路加福音答案的讨论。
例如:对方法或属性获取器的访问可能会触发调用者不知道的初始化。 (例如延迟初始化)此初始化必须显式实现线程安全。
To answer the question correctly: No.
You can't assume that immutable objects are always threadsafe.
But most probably are. See also the discussion on Lukes answer.
For instance: access to methods or property getters could trigger initialization, which is not known by the caller. (Eg. lazy initialization) This initialization must be implemented explicitly threadsafe.
首先,对象必须是真正不可变的——不仅仅是公共接口,所有内部状态都必须被初始化。这禁止例如“获取一次然后缓存”或延迟初始化。
其次,在构造过程中,对象会被修改 - 由于 CPU 上的优化和指令重新排序,写入内存的顺序不一定与您在源代码中看到的顺序相同。
这意味着,如果没有同步,另一个线程可能在对象完全构造之前就已经看到了对该对象的有效引用。
我对 C# memroy 模型不够熟悉,无法准确地告诉您哪个同步是必要的 - 也许其他人可以提供帮助(制作社区维基)
First the object must be truly immutable - not just the public interface but all internal state must be as initialized. This prohibits e.g. "get once then cache" or deferred initialization.
Second, during construction, the objects are modified - and due to optimizations and instruction reordering on the CPU the order in which memory is written is not necessarily the same order you see in the source code.
This means that, without synchronization, another thread may already see a valid reference to the object before it is constructed completely.
I am not familiar enough with the C# memroy model to tell you exactly which synchronization is necessary - maybe someone else can help (made community wiki)