如何使这个线程的代码安全?
public static class Converter
{
public static string ConvertNameToNickname(string name)
{
if (name.Equals("John"))
{
return "Johnathon";
}
return name;
}
}
或者它是否已经是线程安全的,因为“name”是一个局部变量?我只是想确定如果ConvertNameToNickname被两个不同的线程调用,它正在评估的名称没有被其他线程踩到。
< - 编辑 - >
好的其中一些答案非常有用,但我仍然没有找到我想要的答案,所以让我稍微修改一下并提出同样的问题。给定一个mutable-type参数,如何使这段代码线程安全?或者甚至可能吗?如果我在整个方法体周围抛出一个锁{}(如例2所示),在我们进入lock语句块之前,是否仍然可以修改实例变量“name”?
public static class Converter
{
public static string ConvertNameToNickname(StringBuilder name)
{
if (name.ToString().Equals("John"))
{
return "Johnathon";
}
return name;
}
}
示例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;
}
}
}
答案 0 :(得分:7)
或者它是否已经是线程安全的,因为“name”是一个局部变量?
关闭。它是线程安全的,但不是因为局部变量。但是,由于.NET中的string
是不可变的,因此这是线程安全的。在没有同步的情况下保持线程安全的关键始终是使用不可变类型。对于可变类型,即使像.Equals
这样的方法也可能不是线程安全的。
是一个可变类的字符串,这不一定是线程安全的。
编辑:
好的其中一些答案非常有用,但我仍然没有找到我想要的答案,所以让我稍微修改一下并提出同样的问题。给定一个mutable-type参数,如何使这段代码线程安全?或者甚至可能吗?
是的,这有可能发生。但是,它需要某种形式的同步才是正确的。使用锁是一种选择。
如果我在整个方法体周围抛出一个锁{}(如例2所示),在我们进入lock语句块之前,是否仍然可以修改实例变量“name”?
不幸的是,确实如此。锁可防止从两个不同的线程同时调用此代码。从本质上讲,您正在使用“名称”线程的这种特定用途。但是,如果程序中的其他地方使用了“name”,那么在锁定中使用时,仍有可能通过其他功能对其进行修改。这可能会导致一种微妙的竞争条件。
线程安全很难做到。线程安全使用可变类型的最佳选择通常是提供您自己的线程安全类型 - 其中类型本身在内部处理其所需的所有同步,并且公共API完全是线程安全的。这是保证没有其他人会“弄乱”您的数据的唯一方法,即使您正在锁定使用情况。
这是不可变类型发挥作用的地方 - 它们消除了所有这些担忧,因为它们的状态一旦创建就无法改变。任何人都可以使用它们,并构建更多,而不会对类型本身造成风险。
答案 1 :(得分:2)
是的,它已经是线程安全的,因为“name”是分配给不可变对象的局部变量。
本地参数按值传递,因此总是创建值/引用的副本,而不是 ref 参数,在这种情况下,如果它是对a的引用,则可能会出现并发问题字段。