如何编写正确的静态方法 - 多线程安全

3
我理解您希望了解静态方法是否应该像第一个代码片段那样编写,还是我理解错误了?如果不对,请指正。
public static class ExtensionClass
{
 private static SomeClass object1;
 private static StringBuilder sb;

 private static string DoSomething()
 {
    sb.AppendLine(object1.SomeValue);
 }

 public static string ExtensionMethod(this HtmlHelper helper, SomeClass _object1)
 {
    object1 = _object1;
    sb = new StringBuilder();

    DoSomething();

    return sb.ToString();
 }
}

所以我想到了这个方案:
public static class ExtensionClass
{
  private static string DoSomething(ref StringBuilder _sb,SomeClass object1)
  {
    _sb.AppendLine(object1.SomeValue);
  }

  public static string ExtensionMethod(this HtmlHelper helper, SomeClass _object1)
  {
    SomeClass object1 = _object1;
    StringBuilder sb = new StringBuilder();

    DoSomething(ref sb,_object1);

    return sb.ToString();
  }

这段代码是否支持多线程安全?这应该是一个扩展方法,因此它不能是非静态的。或者有没有更好的方法在静态方法中传递非静态对象?


2
风格建议:因为DoSomething不需要替换StringBuilder,所以您不需要(也不想要)ref修饰符。 - itowlson
我认为静态方法并不能保证线程安全。两个不同的线程仍然可以调用相同的静态方法,它可能会在中途休眠,切换到下一个线程并产生不良副作用。编写线程安全代码时必须有点偏执。我没有看到任何锁关键字。我认为你需要它。 - Hamish Grubijan
2
lpthnc:对于他的第一个片段来说是正确的,但是在他的第二个片段中,静态类没有状态,因此没有需要锁定的内容(当然,如果HtmlHelper和SomeClass需要锁定,则需要锁定)。 - itowlson
谢谢,没错。但这可能会改变 ;) - Hamish Grubijan
1个回答

8
第二个代码片段的线程安全性取决于您传入其中的对象。如果某些其他方法在ExtensionMethod运行时操纵HtmlHelper或SomeClass,则可能会遇到问题。但ExtensionMethod有自己的StringBuilder(不像第一个代码片段),因此对ExtensionMethod的多次调用将得到不同的StringBuilder,这样就不会有问题了。
您是正确的,静态方法不应该像第一个代码片段那样编写。正如您已经意识到的那样,如果线程A调用ExtensionMethod,而线程B在线程A仍在其中时调用ExtensionMethod,则sb成员将被更改为引用新的StringBuilder。A迄今为止所做的所有工作都将丢失,并且A和B将从此开始附加到相同的StringBuilder上,产生不良结果!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接