简体   繁体   English

C#线程安全问题

[英]C# Thread Safety Question

How do I make code like this thread safe? 如何使类似该线程的代码安全?

public static class Converter
{
    public static string ConvertNameToNickname(string name)
    {
        if (name.Equals("John"))
        {
            return "Johnathon";
        }

        return name;
    }
}

Or is it already thread safe since "name" is a local variable? 还是因为“名称”是局部变量,它已经是线程安全的了吗? I just want to make sure if ConvertNameToNickname was called by two different threads the name it was evaluating wasn't being stepped on by other threads. 我只是想确保是否两个不同的线程调用了ConvertNameToNickname,它正在评估的名称不会被其他线程踩到。

<--edit--> <-编辑->

Ok some of these answers have been pretty helpful but I still haven't ferreted out the answer I was looking for so let me modify it a bit and ask the same question. 好的,其中一些答案很有帮助,但我仍然没有找出想要的答案,因此让我对其进行一些修改并提出相同的问题。 How would I make this code thread safe given a mutable-type parameter? 给定可变类型的参数,我如何使此代码线程安全? Or is it even possible? 甚至有可能吗? If I throw a lock{} around the entire method body (shown in the example 2) is it still possible for the instance variable "name" to be modified before we enter the lock statement block? 如果我在整个方法主体周围抛出了一个lock {}(如示例2所示),在进入lock语句块之前,是否仍可以修改实例变量“ name”?

public static class Converter
{
    public static string ConvertNameToNickname(StringBuilder name)
    {
        if (name.ToString().Equals("John"))
        {
            return "Johnathon";
        }

        return name;
    }
}

Example 2: 范例2:

private static readonly object _lockObject = new object();

public static class Converter
{
    public static string ConvertNameToNickname(StringBuilder name)
    {
        lock(_lockObject)
        {
            if (name.ToString().Equals("John"))
            {
                return "Johnathon";
            }

            return name;
        }
    }
}

Or is it already thread safe since "name" is a local variable? 还是因为“名称”是局部变量,它已经是线程安全的了吗?

Close. 关。 It is threadsafe, but not because of the local variables. 它是线程安全的,但不是因为局部变量。 However, since string in .NET is immutable, this is thread safe. 但是,由于.NET中的string是不可变的,因此这是线程安全的。 The key to being thread safe without synchronization is always working with immutable types. 保持线程安全而不同步的关键始终在于不可变类型。 With mutable types, even methods like .Equals may not be thread safe. 对于可变类型,即使.Equals类的方法也可能不是线程安全的。

Were string a mutable class, this would not necessarily be thread safe. 如果字符串是可变类,则不一定是线程安全的。


Edit: 编辑:

Ok some of these answers have been pretty helpful but I still haven't ferreted out the answer I was looking for so let me modify it a bit and ask the same question. 好的,其中一些答案很有帮助,但我仍然没有找出想要的答案,因此让我对其进行一些修改并提出相同的问题。 How would I make this code thread safe given a mutable-type parameter? 给定可变类型的参数,我如何使此代码线程安全? Or is it even possible? 甚至有可能吗?

Yes, it is potentially possible. 是的,有可能。 However, it requires synchronization of some form to be correct. 但是,它要求某种形式的同步才能正确。 Using a lock is one option. 使用锁是一种选择。

If I throw a lock{} around the entire method body (shown in the example 2) is it still possible for the instance variable "name" to be modified before we enter the lock statement block? 如果我在整个方法主体周围抛出了一个lock {}(如示例2所示),在进入lock语句块之前,是否仍可以修改实例变量“ name”?

Unfortunately, it is. 不幸的是。 The lock prevents this code from being called simulatenously from two different threads. 锁防止从两个不同的线程模拟调用此代码 In essence, you're making this specific use of "name" thread safe. 本质上,您正在使对“名称”线程的这种特定使用安全。 However, if "name" is used elsewhere in your program, it's still possible that it can be modified by some other function while being used within your lock. 但是,如果在程序的其他位置使用了“名称”,则仍然有可能在锁中使用该名称时通过其他功能对其进行修改。 This could lead to a subtle race condition. 这可能导致微妙的比赛条件。

Thread-safety is tough to get right. 线程安全性很难正确实现。 The best option for thread-safe usage of mutable types is usually to provide your own, thread safe types - where the type itself handles all of its required synchronization internally, and the public API is completely thread safe. 可变类型的线程安全使用的最佳选择通常是提供您自己的线程安全类型-类型本身在内部处理其所有必需的同步,而公共API完全是线程安全的。 This is the only way to guarantee that nobody else will "mess with" your data, even if you're locking around the usage. 这是确保即使有人在限制使用情况的情况下,也没有其他人会“干扰”您数据的唯一方法。

This is where immutable types come into play - they eliminate all of these worries, since their state can't be changed once created. 这是不可变类型起作用的地方-它们消除了所有这些烦恼,因为一旦创建便无法更改其状态。 Anybody can use them, and construct more, without risk to the type itself. 任何人都可以使用它们,并构造更多内容,而不必担心类型本身。

Yes, it's already thread safe since "name" is a local variable assigned to an immutable object. 是的,它已经是线程安全的,因为“名称”是分配给不可变对象的局部变量。

Local parameters are passed by value, so a copy of the value/reference is always made, as opposed to a ref parameter in which case you might have concurrency issues if it was a reference to a field. 局部参数是按值传递的,因此始终会复制值/引用,而不是ref参数,在这种情况下,如果它是对字段的引用,则可能会出现并发问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM