2012-01-12 93 views
25

常规的“线程安全”的MSDN文档为StringBuilder指出,部分:是.NET的StringBuilder的线程安全

...任何实例成员不能保证线程安全...

但这句话感觉就像已经被复制,并在框架粘贴,几乎每一个类:

http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx

然而,由加文·普格这些博客文章提到的StringBuilder线程安全的行为:

http://www.gavpugh.com/2010/03/23/xnac-stringbuilder-to-string-with-no-garbage/

http://www.gavpugh.com/2010/04/01/xnac-avoiding-garbage-when-working-with-stringbuilder/

此外,StringBuilder的由反射透露来源,并附带意见 在SSCLI来源,也提出了许多实施方面的考虑以确保线程安全:

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Text&type=StringBuilder

有没有人有更深入的了解StringBuilder实例是否可以安全地在多个并发线程之间共享?

回答

21

绝对没有;这里是一个简单的例子,从4.0通过反射器解除:

[SecuritySafeCritical] 
public StringBuilder Append(char value) 
{ 
    if (this.m_ChunkLength < this.m_ChunkChars.Length) 
    { 
     this.m_ChunkChars[this.m_ChunkLength++] = value; 
    } 
    else 
    { 
     this.Append(value, 1); 
    } 
    return this; 
} 

该属性只处理调用者,而不是线程安全;这绝对是不是线程安全的。

更新:看他引用的源代码,这显然不是当前的.NET 4.0代码库(比较几种方法)。也许他正在谈论一个特定的.NET版本,或者可能是XNA - 但它通常是而不是。 4.0 StringBuilder不具有具有 a m_currentThread字段,加文的来源材料使用;有一个提示(一个未使用的常量ThreadIDField),它使用存在,但不再...。


如果你想有一个直接反证 - 4.0上运行此;它很可能会给出错误的长度(我在4k区域看到了一些,在2k区域看到了一些 - 它应该恰好为5000),但其他一些方法(例如Append(char))更倾向于抛出异常根据定时:

var gate = new ManualResetEvent(false); 
var allDone = new AutoResetEvent(false); 
int counter = 0; 
var sb = new StringBuilder(); 
ThreadStart work = delegate 
{ 
    // open gate when all 5 threads are running 
    if (Interlocked.Increment(ref counter) == 5) gate.Set(); 
    else gate.WaitOne(); 

    for (int i = 0; i < 1000; i++) sb.Append("a"); 

    if (Interlocked.Decrement(ref counter) == 0) allDone.Set(); 
}; 
for(int i = 0 ; i < 5 ; i++) 
{ 
    new Thread(work).Start(); 
} 
allDone.WaitOne(); 
Console.WriteLine(sb.Length); 
+0

最多3.5个'String.Builder'仍包含线程检查代码。有关更多详细信息,请参阅http://stackoverflow.com/a/3564934/3205。 – skolima 2012-10-18 15:42:53

5

该文档的重点是给你保证。在这种情况下,实例成员不保证是线程安全的,因此您应该将其视为线程安全的,因此依赖于外部同步方法。

,有些事情可能线程是实现细节从而可以也许会改变从框架的一个版本到下一个,或从一个执行到下(其实有很多这样的细节变化在框架版本中; Eric Lippert有一些帖子详细介绍了其中的一些)。不要依赖它。

(换句话说:不要写代码一种实施方式,它编写针对接口和合同它是类的元数据和其在这种情况下的文件)

0

MSDN documentation

任何公共静态此类型的成员(Visual Basic中的Shared)是 线程安全的。任何实例成员不保证是线程 安全。