Абсолютно нет; Вот простой пример, снятый с 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
), что она использовала для существования, но ... больше нет.
Если вы хотите direct disproof - запустите это на 4.0; это, скорее всего, даст неправильную длину (я видел несколько в области 4k, несколько в области 2k - это должно быть ровно 5000), но некоторые другие методы Append
(например, 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);