1

我正在从多个线程调用一个简单的字符串连接函数。我按照我的想法锁定了它。做了很多带锁或不带锁的测试。它从未失败过。

我的问题是:字符串连接是否必须被锁定?

private readonly object idLock = new object();

private string GetId(string input1, string input2, string input3)
{
    lock (idLock)
        return string.Format("{0}; {1}; {2}", input1, input2, input3);
}

我使用 PLINQ 测试了以下变体 - 10000000 次循环。以毫秒为单位的时间是:

// Time 5446
lock (idLock)
    return string.Format("{0}; {1}; {2}", input1, input2, input3);

// Time 3728
lock (idLock)
    return input1 + "; " + input2 + "; " + input3;

// Time 953
return string.Format("{0}; {1}; {2}", input1, input2, input3);

// Time 652
return input1 + "; " + input2 + "; " + input3;

完整的测试代码在这里:测试并行字符串连接

4

2 回答 2

3

不,它不必有任何锁定结构。

任何纯方法都可以在多线程环境中正常运行。

“纯”是指一种方法:

  • 给定相同的参数值,该函数始终评估相同的结果值。函数结果值不能依赖于任何可能随着程序执行或程序的不同执行而改变的隐藏信息或状态,也不能依赖于来自 I/O 设备的任何外部输入。
  • 结果的评估不会导致任何语义上可观察的副作用或输出,例如可变对象的突变或输出到 I/O 设备。

(来源:维基百科:纯函数

在您的情况下,字符串连接本身在多线程环境中很好,不需要任何锁定结构。

但是,如果您要连接从其他线程可以更改的字段或属性中读取的字符串,那么您将需要锁定或类似的东西以确保系统的稳定性,但您问题中的示例代码,没有。

于 2013-07-06T18:41:44.317 回答
3

我的问题是:字符串连接是否必须被锁定?

不,您不需要任何锁定。MSDN 声明System.String线程安全的(它的方法也是如此,包括Format方法)。

这并不奇怪,因为 .Net 字符串是不可变的,这意味着它的值在创建后无法更改。不可变类型本质上是线程安全的,因为它们的值不能被一个线程更改,而另一个线程也在访问它。如果您的输入参数是任何其他可变的引用类型,那么您可能会遇到潜在的问题。

于 2013-07-06T19:02:56.947 回答