2

我的问题是如果我有时在同一个字符串上使用多线程

字符串不会被替换。(我在记事本上写了这个,所以语法可能是

错误的)

使用 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")
    }
    }
}

现在有时某些元素不会被替换。所以我对此的解决方案是调用 container.Replace

方法并做一个“锁定”,但它是正确的方法吗?

private class ModiflyString
{
        public void Do(string x, string y)
            {
                lock (this)
                {
                    fileInput.Replace(x, y);
                }
            }
}
4

3 回答 3

6

您应该锁定 StringBuilder 对象本身(在替换函数内):

lock (container)
{
   container.Replace("this", "With this");
}

或创建一个单独的锁对象:

static object _stringLock = new object();

...

lock(stringLock)
{
    container.Replace("this", "With this");
}
于 2009-08-12T20:19:02.853 回答
3

当您创建超过 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

然后你可以(线程)安全地使用:

   lock(syncLock)
   {
       container.Replace(...);
   }
于 2009-08-12T20:14:31.847 回答
2

只要两个线程具有相同的 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”(您不能锁定字符串,因为它是一种值类型)。

于 2009-08-12T20:21:56.590 回答