是否锁定:并行字符串连接

本文关键字:字符串 连接 并行 锁定 是否 | 更新日期: 2023-09-27 18:21:13

我从多个线程调用一个简单的字符串串联函数。我把它锁上了。进行了多次带锁或不带锁的测试。它从未失败。

我的问题是:字符串串联必须被锁定吗?

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;

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

是否锁定:并行字符串连接

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

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

我所说的"纯"是指一种方法:

  • 给定相同的参数值,函数总是计算相同的结果值。函数结果值不能依赖于任何隐藏的信息或状态,这些信息或状态可能随着程序执行的进行或在程序的不同执行之间发生变化,也不能依赖于来自I/O设备的任何外部输入
  • 对结果的评估不会导致任何语义上可观察到的副作用或输出,例如可变对象的突变或I/O设备的输出

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

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

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

我的问题是:字符串串联必须被锁定吗?

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

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