2009-08-12 104 views
0

我的问题是,如果我使用多线程上相同的字符串有时访问使用多线程相同的字符串(StringBuilder)对

字符串将不会进行更换。(我写了这个记事本上这样的语法可能

使用错误)

System.Thread ...其他ofcourse

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); 
       } 
      } 
} 

回答

5

您应该锁定StringBuilder对象本身(内部的替换功能):

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

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

static object _stringLock = new object(); 

... 

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

我从来没有想过锁定stringbuilder本身,非常好。谢谢, – 2009-08-12 20:26:08

+0

菲尔的第二个例子就是当我提到一个“虚拟”对象时所指的。然而,我认为他第一个锁定容器的例子是他们中最好的。由于容器表示线程之间共享的数据,因此您需要锁定该数据。如果您使用我的示例,则存在以下问题:如果您的线程尝试为完全独立的容器调用ModifyString.Do,则它们将相互阻塞,即使它们所使用的容器完全不同。所以你会伤害表现。所以我的例子实际上是一个糟糕的实现。 – AaronLS 2009-08-12 20:28:39

+0

感谢@arronls现在我的程序正在工作:) – 2009-08-12 20:39:29

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 

,然后你可以(thread-)安全使用:

lock(syncLock) 
    { 
     container.Replace(...); 
    } 
+0

我确实创建了一个对象,这就是为什么我能够使用“this” – 2009-08-12 20:17:58

+0

但是您是否实例化了_only_ 1?这就是我想说的。 – 2009-08-12 20:20:23

+1

不,您创建了_many_ objects- ModifyString的每个实例都是它自己的对象。 – 2009-08-12 20:20:25

2

只要两个线程都具有相同的ModifyString类实例,这样就可以正常工作。换句话说,这将工作,因为上了锁“这个”必须在同一个实例的锁:

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

有些人会真正创建一个“虚拟”的对象上,而不是用“本”(你不能串锁进行锁定,因为它是值类型)。

+0

StringBuilder不是一个值类型,你知道吗? – 2009-08-12 20:32:31

+0

我没有说弦乐器,我说弦乐。 – AaronLS 2009-08-12 20:37:28