Доступ к той же строке (StringBuilder) с использованием многопоточности

StackOverflow https://stackoverflow.com/questions/1268446

  •  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» (вы не можете заблокировать строку, поскольку это тип значения).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top