首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是.NET的StringBuilder线程安全

是.NET的StringBuilder线程安全
EN

Stack Overflow用户
提问于 2012-01-12 07:15:42
回答 3查看 18.4K关注 0票数 34

StringBuilder的MSDN文档中的常规“线程安全”部分指出:

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

但是,这个声明似乎已经被复制和粘贴到了框架中的几乎每个类:

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

然而,Gavin Pugh的这些博客文章提到了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/

此外,Reflector揭示的StringBuilder源代码以及SSCLI源代码中的注释也提出了许多实现考虑因素,以确保线程安全:

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

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-01-12 07:27:16

绝对不是;这里有一个简单的示例,它是通过反射器从4.0中提取的:

代码语言:javascript
复制
[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字段,Gavin的源代码使用该字段;有一个提示(未使用的常量ThreadIDField)表明使用存在,但是.不再。

如果您想要一个直接拒绝--在4.0上运行这个;它很可能会给出错误的长度(我在4k区域看到了一些,在2k区域中有几个--应该正好是5000),但是其他一些Append方法(例如Append(char))更有可能抛出异常,这取决于时间:

代码语言:javascript
复制
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);
票数 31
EN

Stack Overflow用户

发布于 2012-01-12 07:18:00

文件的全部目的是给你保证。在这种情况下,在实例成员上,没有任何保证是线程安全的,因此您应该将其视为线程安全,因此依赖于外部同步方法。

有些东西可能是threadsafe,这是一个实现细节,它可以而且可能确实会从框架的一个版本更改到下一个版本,或者从一个实现更改到下一个版本(事实上,在框架版本中有很多这样的细节更改;Eric Lippert有一些文章详细介绍了其中的一些细节)。不要依赖它。

(换句话说:不要为实现编写代码,而是根据接口和契约编写代码,在本例中,接口和契约是类及其文档的元数据。)

票数 6
EN

Stack Overflow用户

发布于 2014-04-15 15:59:40

来自MSDN文档

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8831385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档