是C#6吗? (Elvis op)线程安全吗?如果是这样,怎么办? [英] Is C# 6 ?. (Elvis op) thread safe? If so, how?

查看:99
本文介绍了是C#6吗? (Elvis op)线程安全吗?如果是这样,怎么办?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

预先致歉:这个问题来自一个顽固,没有改革的C ++开发人员,他们试图学习高级C#。请考虑以下内容:

Apologies in advance: this question comes from a hard-core, unreformed C++ developer trying to learn advanced C#. Consider the following:

if (myUserDefinedObject != null)
{
    myUserDefinedObject.ToString();
}

这显然不是线程安全的。另一方面,我看过两个教程? (空条件运算符或猫王运算符),例如

This is obviously not thread safe. On the other hand, I've seen two tutorials that say ?. (the Null Conditional Operator or 'Elvis Operator') for example,

myUserDefinedObject?.ToString();

IS 线程安全。除非编译器将[mutex?]锁围绕在表皮下(颤抖),否则我不明白这是怎么回事。如果这个惯用语是线程安全的,那么有人可以向我指出如何实现此目的的技术描述吗?如果不是线程安全的,是否有人引用实际上说不是?

IS thread safe. Unless the compiler wraps a [mutex?] lock around it under the covers (shiver), I don't understand how that can be true. If this idiom is thread safe, can someone point me to a technical description of how that is accomplished? If it's not thread safe, does anyone have a reference that actually says it is not?

推荐答案

我想澄清一下BJ Myers的(正确答案。

I want to clarify BJ Myers's (correct) answer.

在C#中,事件可以被视为委托类型的字段-就像属性可以被视为属性类型的字段一样-该字段的值可以为null。如果不幸的是在一个线程上修改了事件处理程序而另一个线程正在尝试调用该事件处理程序,则可能会遇到以下情况:

In C# an event can be thought of as a field of delegate type -- just as a property can be thought of as a field of the property type -- and the value of that "field" can be null. If you are in the unfortunate situation of having an event handler being modified on one thread while another thread is attempting to invoke it, you can get into the situation where:

if (this.SomeEvent != null) 
    this.SomeEvent( ... );

不是线程安全的。可以更改该值,以使其在检查之前为非null,在检查之后为null,并且程序崩溃。

is not threadsafe. The value could be mutated so that it is non-null before the check, null after the check, and the program crashes.

使此线程安全的通常方法,我建议您使用该术语,是将值复制到本地,然后测试本地是否为空。这样的好处是不会因空取消引用而崩溃。但是,聪明的开发人员会注意到仍然有比赛!序列可以是

The usual way to make this "threadsafe", and I use the term advisedly, is to copy the value to a local and then test the local for null. This has the benefit of not crashing with a null dereference. However, the clever developer will note that there is still a race! The sequence can be


  • 在线程A上缓存的非空事件处理程序

  • 将事件处理程序设置为线程B上的null

  • 事件处理程序所需的状态在线程B上被破坏

  • 事件处理程序在线程A上运行并严重死亡

  • Non-null event handler cached on thread A
  • Event handler set to null on thread B
  • State needed by event handler is destroyed on thread B
  • Event handler runs on thread A and dies horribly

因此从某种意义上说,这种模式不是线程安全的。如果您处于这个不幸的位置,则您有责任确保实现了适当的线程逻辑,以免发生这种情况。您可以根据需要执行此操作。如果您希望能够在一个线程上调用事件处理程序而在另一个线程上更改事件时具有(可疑的)好处,那么您就必须付费以使其安全,或处理竞争条件错误。

So in that sense this pattern is not "thread safe". If you are in this unfortunate position you are responsible for ensuring that the appropriate threading logic is implemented so that this cannot happen. You can do that however you want. If you want the (questionable) benefits of being able to call an event handler on one thread while mutating the event on another thread, then you've got to pay either to make it safe, or deal with race condition bugs.

我个人会避免这种情况,例如鼠疫,但我不够聪明,无法编写正确的多线程代码。

I personally would avoid this situation like the plague, but I'm not smart enough to write correct multithreaded code.

现在,对于实际问题:

some_expression ?. ToString();

temp = some_expression
temp == null ? null : temp.ToString()

您认为后者的代码线程安全吗?

Is the latter code "threadsafe" in your opinion?

这篇关于是C#6吗? (Elvis op)线程安全吗?如果是这样,怎么办?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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