代码之家  ›  专栏  ›  技术社区  ›  omatase

C#螺纹安全问题

  •  0
  • omatase  · 技术社区  · 15 年前

    如何使这样的代码线程安全?

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

    <--编辑-->

    好吧,其中一些答案非常有用,但是我仍然没有找到我想要的答案,所以让我修改一下,问同样的问题。如果给定一个可变的类型参数,如何使代码线程安全?或者有可能吗?如果我在整个方法体周围抛出一个锁{}(如示例2中所示),那么在进入lock语句块之前,实例变量“name”是否仍有可能被修改?

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

    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;
            }
        }
    }
    
    2 回复  |  直到 15 年前
        1
  •  7
  •   Reed Copsey    15 年前

    或者它已经是线程安全的,因为“name”是一个局部变量?

    接近。它是线程安全的,但不是因为局部变量。然而,自从 string 在.NET中是不可变的,这是线程安全的。在没有同步的情况下保持线程安全的关键是始终使用不可变类型。对于可变类型,甚至像 .Equals 可能不是线程安全的。

    如果string是一个可变类,那么它就不一定是线程安全的。


    好吧,其中一些答案非常有用,但是我仍然没有找到我想要的答案,所以让我修改一下,问同样的问题。如果给定一个可变的类型参数,如何使代码线程安全?或者有可能吗?

    是的,这是可能的。但是,它需要某种形式的同步才能正确。使用锁是一种选择。

    不幸的是,的确如此。锁防止 此代码 从两个不同的线程模拟调用。实际上,您正在使“name”的这种特定用法成为线程安全的。但是,如果在程序的其他地方使用了“name”,那么在锁中使用时,它仍然有可能被其他函数修改。这可能会导致一个微妙的比赛条件。

    这就是不可变类型发挥作用的地方——它们消除了所有这些担忧,因为它们的状态一旦创建就无法更改。任何人都可以使用它们,并构造更多,而不会给类型本身带来风险。

        2
  •  2
  •   Mark Cidade    15 年前

    本地参数是按值传递的,因此总是创建值/引用的副本,而不是 裁判