1
1
从某种意义上说,您将得到一个正确初始化的对象是安全的,但是几个线程可能同时创建对象,而一个线程可能返回一个刚创建的不同线程的对象。 如果编译器输入该方法,它仍然不会与第一个代码相同。由于对对象的引用保存在局部变量中,直到初始化,所以它仍然是安全的。 您可以自己内联该方法,无需将代码放在单独的方法中以确保其安全:
如果要防止多个对象由单独的线程创建,则需要使用锁。 |
2
2
在某些情况下,volatile可能是一个性能选项,以避免使用锁的额外冲击,但它不解决争用条件的线程安全问题,这是您的第三个示例(有问题的例子)所具有的。
为了确保另一个线程没有检索到未初始化的实例,在拥有完全初始化的实例之前,不应将其分配给静态变量。一旦他们看到一个非空值,他们就会知道它是好的。
编辑
:(更正)虽然我认为避免冗余工作更理想(见下文),但对于您的用例,允许重新生成和替换静态引用(如您所拥有的,或Guffa的版本)仍然是“安全的”,因为每个引用
我建议这样做:
这样做的好处是只做一次init工作,同时也避免了锁争用开销,除非实际上需要这样做…但仍然是安全的。(如果您想确定volatile是否传播出去,可以如上所述使用volatile,但是如果没有它,这也应该“有效”;在看到
我一直守护着你
|
3
1
要回答第二次编辑,如果您的初始化方法需要一段时间,则另一个线程可能会像k一样,如果对象不是空的,则拉入其未初始化状态。我建议您使用一个用于空检查和初始化的锁来确保只有在完全初始化时才检索对象。 如果您希望它是完全线程安全的,这可以帮助:
|
4
1
即使方法是内联的,本地也不会被优化掉,对字段的写入也只会发生一次。 所以最后一个例子 线程安全 . 通常,当变量有多个访问权限时,局部变量不会被优化并替换为全局变量。 |
5
0
如果我能在clippy上发布一分钟的话:“看起来你正在尝试实现singleton模式。”请看 Jon Skeet's canonical article on the subject . |
6
0
为什么不将initialize方法移动到myObject的tor中,并用一个调用初始化它? |
7
0
即使没有编译器优化,它仍然是不安全的。在这种情况下,volatile没有帮助——它只是设计用来保护变量不被修改为“在封面下”。假设两个线程在完全相同的时间通过了空检查——您最终会两次调用“LoadMyObject”,在这种情况下,这可能是正常的,也可能不是。这是一个toctou错误(检查时间/使用时间)。基本上,您必须使整个getMyObject方法的主体安全,包括检查(即使该调用同步)。 |
8
0
这是我的看法:
|
9
0
在我看来,这似乎过于乐观了。与其深入了解编译器所做工作的细微之处,不如选择最适合您的方法:
这完全取决于你想付多少罚金。对于一个单身汉,你要付表演罚金。对于其他两个选项,您需要支付内存罚金。 要使其线程静态,只需执行以下操作:
|
Robert King · Unity C#语法问题-转换位置 1 年前 |
JBryanB · 如何从基本抽象类访问类属性 1 年前 |
law · 检查答案按钮的输入字符串格式不正确 2 年前 |
i_sniff_ket · 在unity之外使用unity类 2 年前 |