Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用多线程访问同一字符串(StringBuilder)_C#_String_Stringbuilder - Fatal编程技术网

C# 使用多线程访问同一字符串(StringBuilder)

C# 使用多线程访问同一字符串(StringBuilder),c#,string,stringbuilder,C#,String,Stringbuilder,我的问题是如果我在同一个字符串上使用多线程 字符串不会被替换。(我在记事本上写了这个,所以语法可能不正确。) (错) 正在使用System.Thread。。。当然还有其他的 class .... { private static StringBuild container = new StringBuilder(); static void Main(...) { container.Append(Read From File(Kind of long));

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

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

(错)

正在使用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);
                }
            }
}

当您创建多个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(...);
   }

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

或创建单独的锁定对象:

static object _stringLock = new object();

...

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

只要两个线程具有相同的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")
        }
    }
}
如果您执行以下操作,它将不起作用,因为锁(此)将不起作用,因为它们是两个独立的实例:

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”(您不能锁定字符串,因为它是值类型)。

我确实创建了一个对象,这就是为什么我可以使用“this”否,您创建了许多对象-ModifyString的每个实例都是它自己的对象。希望我的示例能够说明Henk和Joel试图向您指出的问题。我从未想过锁定stringbuilder本身,非常好。谢谢,Phil的第二个例子就是我提到的“虚拟”对象。然而,我认为他锁集装箱的第一个例子是最好的。由于容器表示线程之间共享的数据,因此需要锁定该数据。如果使用我的示例,则会出现一个问题,即如果有线程试图调用ModifyString.Do来处理完全不同的容器,那么它们将相互阻止,即使它们使用的容器完全不同。所以你会影响表演。所以我的例子是一个很糟糕的实现。我不能编辑这个,不管怎样,锁定对象本身还是锁定“虚拟”对象更好我没有说stringbuiler,我说的是string。
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")
        }
    }
}