引用赋值和读取是原子操作吗?
我发现了几个关于同一主题但与一般变量(值和引用类型)相关的问题 这个问题接受的答案是:
分区 I CLI 规范第 12.6.6 节规定:“当对某个位置的所有写访问大小相同时,一致的 CLI 应保证对不大于本机字大小的正确对齐的内存位置的读写访问是原子的。”
引用变量(即类)是指针,等于本机字大小,但我有几个疑问:
引用是否保证位于正确对齐的内存位置?
我不明白最后一部分。这意味着什么? “...当对某个位置的所有写访问大小相同时。”
简而言之,obj2 是否保证在以下代码中循环的每次迭代中都有效?
class MyClass
{
private OtherClass m_Object;
void Thread1()
{
while(true)
{
OtherClass obj1 = new OtherClass();
m_Object = obj1;
}
}
void Thread2()
{
while (true)
{
OtherClass obj2 = m_Object;
// Is obj2 guaranteed to be valid?
obj2.Check();
}
}
}
I have found several questions about this same topic but related to general variables (value and reference types)
The accepted answer from this question says:
Partition I, Section 12.6.6 of the CLI spec states: "A conforming CLI shall guarantee that read and write access to properly aligned memory locations no larger than the native word size is atomic when all the write accesses to a location are the same size."
Reference variables (i.e. classes) are pointers, equal to the native word size, but I have a couple doubts:
Are references guaranteed to be in properly aligned memory locations?
I don't understand the last part. What does this mean? "...when all the write accesses to a location are the same size."
In short, is obj2 guaranteed to be valid in every iteration of the loop in the following code?
class MyClass
{
private OtherClass m_Object;
void Thread1()
{
while(true)
{
OtherClass obj1 = new OtherClass();
m_Object = obj1;
}
}
void Thread2()
{
while (true)
{
OtherClass obj2 = m_Object;
// Is obj2 guaranteed to be valid?
obj2.Check();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,一切都保证正确对齐,除非你故意不遗余力地错位东西,这意味着引用分配/读取保证是原子的。
CLI 规范的第 12.6.6 节继续说道:
规范第 12.6.2 节中还有关于对齐等的更多详细信息。
请注意,在您的示例代码中,线程 2 中的读取保证是原子的,但不能保证实际看到线程 1 所做的任何更改:在不强制执行内存屏障或易失性的情况下,每个线程都可以使用其拥有
m_Object
字段的“视图”,而不会看到其他线程所做的更改。因此,例如,线程 1 可能会(原子)写入自己的
m_Object
视图,但数据实际上仅保存在寄存器或 CPU 缓存中,而从未提交到主内存。类似地,线程 2 也可以对m_Object
进行(原子)读取,但实际上是从寄存器或 CPU 缓存而不是主内存中读取。Yes, everything is guaranteed to be properly aligned unless you deliberately go out of your way to misalign stuff, meaning that reference assignment/reading is guaranteed to be atomic.
Section 12.6.6 of the CLI spec goes on to say this:
There are also further details about alignment etc in section 12.6.2 of the spec.
Note that in your example code, the read in thread 2 is guaranteed to be atomic, but it's not guaranteed to actually see any changes made by thread 1: without enforcing memory barriers or volatility each thread can use its own "view" of the
m_Object
field without ever seeing changes made by other threads.So, for example, thread 1 could be making (atomic) writes into its own view of
m_Object
, but the data is only ever actually held in a register or CPU cache and never comitted to main memory. Similarly, thread 2 could also be making (atomic) reads ofm_Object
, but actually reading from a register or CPU cache rather than main memory.