是.NET的StringBuilder的线程安全 [英] Is .NET's StringBuilder thread-safe

查看:160
本文介绍了是.NET的StringBuilder的线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

MSDN文档的StringBuilder的正规线程安全部分指出,任何实例成员都不能保证是线程安全的,但这种说法感觉它已经被复制和粘贴,几乎每一个类的框架:

The regular "Thread Safety" section of the MSDN documentation for StringBuilder states that "any instance members are not guaranteed to be thread safe" but this statement feels like it has been copied and pasted for almost every class in the Framework:

<一个href="http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx">http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx

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

However, these blog posts by Gavin Pugh mention thread-safe behaviours of StringBuilder:

<一个href="http://www.gavpugh.com/2010/03/23/xnac-stringbuilder-to-string-with-no-garbage/">http://www.gavpugh.com/2010/03/23/xnac-stringbuilder-to-string-with-no-garbage/

<一个href="http://www.gavpugh.com/2010/04/01/xnac-avoiding-garbage-when-working-with-stringbuilder/">http://www.gavpugh.com/2010/04/01/xnac-avoiding-garbage-when-working-with-stringbuilder/

此外,StringBuilder的源码,反射显现,伴随的评论  在SSCLI源,也表明许多实施注意事项,以保证线程安全:

Additionally, the source of StringBuilder revealed by Reflector, and the accompanying comments in the SSCLI source, also suggest many implementation considerations to ensure thread-safety:

<一个href="http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Text&type=StringBuilder">http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Text&type=StringBuilder

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

Does anyone have any more insight into whether a StringBuilder instance is safe to share among multiple concurrent threads?

推荐答案

当然不是;这里有一个简单的例子,通过反射器从4.0提升:

Absolutely not; here's a simple example lifted from 4.0 via reflector:

[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;
}

属性只是处理来电,不是线程安全的;这是绝对不是线程安全的。

The attribute just handles callers, not thread-safety; this is absolutely not thread-safe.

更新:在看,他引用的来源,这显然不是目前的.NET 4.0 code基(比较几个方法)。也许他是在谈论一个特定的.NET版本,或者XNA - 但它的不可以的一般情况。 4.0 的StringBuilder 有无 m_currentThread 字段,加文的源材料使用;有一个提示(未使用常数 ThreadIDField )的使用存在,但是......不下去了。

Update: looking at the source he references, this is clearly not the current .NET 4.0 code-base (comparing a few methods). Perhaps he is talking about a particular .NET version, or maybe XNA - but it is not the case in general. The 4.0 StringBuilder does not have a m_currentThread field, which Gavin's source material uses; there's a hint (an unused constant ThreadIDField) that it used to exist, but... no longer.

如果你想有一个直接反证 - 4.0上运行此;它很可能会给出错误的长度(我已经看到了一些在4K区域,在2K地区的几个 - 这应该是完全5000),但一些其他的追加方法(追加(字符)为例)往往更容易抛出异常,这取决于时间:

If you want a direct disproof - run this on 4.0; it will most likely give the wrong length (I've seen a few in the 4k region, a few in the 2k region - it should be exactly 5000), but some other Append methods (Append(char) for example) tend more likely to throw exceptions, depending on timing:

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);

这篇关于是.NET的StringBuilder的线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆