class Test {
public string GetData() {
StringBuilder sb = new StringBuilder();
sb.Append("aassffss");
sb.Append("bbhhhhh");
return sb.ToString();
}
}
// calling from multithreads,as below,
// from each thread i will create new
// instance and call method.
Test t = new Test();
t.GetData();
В соответствии с MSDN. любой член экземпляра класса StringBuilder
не является потокобезопасным. поэтому я считаю, что это не потокобезопасность. Я прав?
Этот код является потокобезопасным, поскольку экземпляры не разделяются между потоками.
Вы столкнулись бы с проблемой, если бы у вас был один экземпляр, разделенный между несколькими потоками. Затем, если у вас было несколько вызовов метода экземпляра из разных потоков, в том же экземпляре код был бы небезопасным.
GetData()
и, кажется, думаете: когда этот метод выполняется из разных потоков, они обращаются к одному и тому же экземпляру. Но они этого не делают. Каждый раз, когда вы вызываете этот метод, создается новый экземпляр . Поэтому, как объясняет Дэвид, никакие экземпляры StringBuilder не разделяются между потоками.
Предположим, что у вас есть два потока t0 и t1. Оба используют общий экземпляр StringBuilder sb
. Каждый поток выполняет следующие соответствующие методы: T0
T1
:
public void T0()
{
sb.Append("0");
sb.Append("0");
}
public void T1()
{
sb.Append("1");
sb.Append("1");
}
Затем вы можете получить следующий результат на sb.ToString()
0011
0101
0110
1010
1100
Таким образом, любая из приведенных выше комбинаций является разумным результатом для метода ToString
при использовании двух потоков, вызывающих несинхронизированную общую переменную. В этом случае общая переменная является экземпляром sb
где проблема лежит внутри класса. Внутренний буфер будет заполнен вызовом метода Append
в этом экземпляре. Эта переменная буфера является переменной, которая эффективно используется совместно.
Вернемся к вашему вопросу: ваш код является потокобезопасным, если вы не делитесь экземпляром с другими потоками и вызываете методы, такие как общие переменные. Если используется общий доступ, вам необходимо синхронизировать вызовы с ним самостоятельно. Затем рассмотрим реализацию синхронизированной обертки.
Test.GetData()
он всегда будет возвращать новый экземпляр каждому вызывающемуTest.GetData()
. Хотя даже это было бы потокобезопасным. Но вызов любого члена самогоStringBuilder
может чередоваться несколькими потоками