使用集合初始值设定项时,另一个线程可以看到部分创建的集合吗? [英] Can another thread see partially created collection when using collection initializer?

查看:53
本文介绍了使用集合初始值设定项时,另一个线程可以看到部分创建的集合吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下以下方法中的C#代码:

Imagine this C# code in some method:

SomeClass.SomeGlobalStaticDictionary = new Dictionary<int, string>()
{
    {0, "value"},
};

比方说,没有人使用任何显式的内存屏障或锁定来访问字典.

Let's say no one is using any explicit memory barriers or locking to access the dictionary.

如果未进行优化,则全局字典应为null(初始值)或具有一个条目的正确构造的字典.

If no optimization takes place, then the global dictionary should be either null (initial value) or a properly constructed dictionary with one entry.

问题是:可以重新排序Add调用并分配给SomeGlobalStaticDictionary的效果,以便其他线程看到空的非null SomeGlobalStaticDictionary(或任何其他无效的部分构造的字典吗?)

The question is: Can the effect of the Add call and assigning to SomeGlobalStaticDictionary be reordered such that some other thread would see an empty non-null SomeGlobalStaticDictionary (or any other invalid partially constructed dictionary?)

如果SomeGlobalStaticDictionary是易变的,答案是否会更改?

Does the answer change if SomeGlobalStaticDictionary is volatile?

阅读 http://msdn.microsoft.com/en-us/magazine/jj863136.aspx (及其第二部分),我了解到,理论上,仅仅因为在源代码中分配了一个变量,其他线程由于多种原因可能会看到不同的结果.我查看了IL代码,但问题是是否允许JIT编译器和/或CPU在分配SomGlobalStaticDictionary之前不清空" Add调用对其他线程的影响.

After reading http://msdn.microsoft.com/en-us/magazine/jj863136.aspx (and also its second part) I learned that in theory just because one variable is assigned in source code other threads might see it differently due to many reasons. I looked at the IL code but the question is whether the JIT compiler and/or CPU are allowed to not "flush" the effect of the Add call to other threads before the assignment of the SomGlobalStaticDictionary.

推荐答案

首先,我不知道您问题的答案,但我可以帮助您将其简化为本质:

Let me start by saying that I do not know the answer to your question, but I can help you simplify it down to its essence:

unsafe class C
{
    static int x;  // Assumed to be initialized to zero
    static int *p; // Assumed to be initialized to null
    static void M()
    {
        int* t = &C.x;
        *t = 1;
        C.p = t;
    }
    ...

这里 int 代表字典, p 代表引用字典的字段, t 是临时创建的,并向字典中添加元素被建模为使字段 x 的值突变.因此,这里的事件顺序是:获取字典的存储并将其保存在临时文件中,然后对所引用的事物进行变异,然后发布结果.

Here int is standing in for the dictionary, p is standing in for your field that references a dictionary, t is the temporary created, and adding an element to the dictionary is modeled as mutating the value of field x. So the sequence of events here is: obtain storage for the dictionary and save that in a temporary, then mutate the thing referred to, and then publish the result.

问题是,在C#内存模型下,是否允许另一个线程上的观察者看到 Cp 指向 x x 仍为零.

The question is whether under the C# memory model, an observer on another thread is permitted to see that C.p is pointing to x and that x is still zero.

就像我说的那样,我不确定答案是什么;我很想找出答案.

Like I said, I do not know for certain the answer to that; I would be interested to find out.

不过,我的头顶上:为什么不可能成为可能? p x 可以位于完全不同的内存页面上.假设在某些处理器上已经预取了 x 的值,但尚未预取 p 的值.该处理器能否观察到 p 不为空,但 x 仍为零?是什么在阻止呢?

Off the top of my head though: why should that not be possible? p and x can be on completely different pages of memory. Suppose on some processor the value of x has been pre-fetched but p has not. Could that processor observe that p is not null but x is still zero? What's stopping that?

这篇关于使用集合初始值设定项时,另一个线程可以看到部分创建的集合吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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