Доступ к той же строке (StringBuilder) с использованием многопоточности
-
13-09-2019 - |
Вопрос
Моя проблема в том, что я когда-нибудь использую многопоточную обработку одной и той же строки.
строка не будет заменена. (Я написал это в блокноте, поэтому синтаксис может быть
неправильный)
используя System.Thread...Другие, конечно
class ....
{
private static StringBuild container = new StringBuilder();
static void Main(...)
{
container.Append(Read From File(Kind of long));
Thread thread1 = new Thread(Function1);
Thread thread2 = new Thread(Function2);
thread1.Start();
thread2.Start();
//Print out container
}
static void Function1
{
//Do calculation and stuff to get the Array for the foreach
foreach (.......Long loop........)
{
container.Replace("this", "With this")
}
}
//Same goes for function but replacing different things.
static void Function2
{
//Do calculation and stuff to get the Array for the foreach
foreach (.......Long loop........)
{
container.Replace("this", "With this")
}
}
}
Теперь иногда какой-то элемент не заменяется.Итак, мое решение — вызов контейнера. Замените его на другой
метод и выполнить «блокировку», которая работает, но правильно ли это?
private class ModiflyString
{
public void Do(string x, string y)
{
lock (this)
{
fileInput.Replace(x, y);
}
}
}
Решение
Вам следует заблокировать сам объект StringBuilder (внутри функций замены):
lock (container)
{
container.Replace("this", "With this");
}
или создайте отдельный объект блокировки:
static object _stringLock = new object();
...
lock(stringLock)
{
container.Replace("this", "With this");
}
Другие советы
Ваша блокировка не будет работать, если вы создадите более 1 объекта ModifyString, и я предполагаю, что вы это делаете.
Простая версия:
public void Do(string x, string y)
{
lock (fileInput)
{
fileInput.Replace(x, y);
}
}
Возможно, было бы лучше создать отдельный объект для блокировки, но приведенное выше лучше показывает принцип:все конкурирующие потоки должны блокироваться на одном и том же объекте.
Стандартный подход будет выглядеть так:
private static StringBuild container = new StringBuilder();
private static object syncLock = new object(); // simple object, 1-1 with container
и тогда вы можете (thread-) безопасно использовать:
lock(syncLock)
{
container.Replace(...);
}
Это будет работать нормально, если оба потока имеют один и тот же экземпляр класса ModifyString.Другими словами, это будет работать, потому что блокировка «this» должна быть блокировкой того же экземпляра:
class Blah
{
private static StringBuild container = new StringBuilder();
private static ModifyString modifyString = new ModifyString();
static void Main(...)
{
container.Append(Read From File(Kind of long));
Thread thread1 = new Thread(Function1);
Thread thread2 = new Thread(Function2);
thread1.Start();
thread2.Start();
//Print out container
}
static void Function1
{
//Do calculation and stuff to get the Array for the foreach
foreach (.......Long loop........)
{
modifyString.Do("this", "With this")
}
}
//Same goes for function but replacing different things.
static void Function2
{
//Do calculation and stuff to get the Array for the foreach
foreach (.......Long loop........)
{
modifyString.Do("this", "With this")
}
}
}
Это будет НЕТ сработает, если вы сделаете следующее, потому что lock(this) не будет работать, поскольку это два отдельных экземпляра:
class Blah
{
private static StringBuild container = new StringBuilder();
static void Main(...)
{
container.Append(Read From File(Kind of long));
Thread thread1 = new Thread(Function1);
Thread thread2 = new Thread(Function2);
thread1.Start();
thread2.Start();
//Print out container
}
static void Function1
{
ModifyString modifyString = new ModifyString();
//Do calculation and stuff to get the Array for the foreach
foreach (.......Long loop........)
{
modifyString.Do("this", "With this")
}
}
//Same goes for function but replacing different things.
static void Function2
{
ModifyString modifyString = new ModifyString();
//Do calculation and stuff to get the Array for the foreach
foreach (.......Long loop........)
{
modifyString.Do("this", "With this")
}
}
}
Некоторые люди на самом деле создают «фиктивный» объект для блокировки вместо использования «this» (вы не можете заблокировать строку, поскольку это тип значения).