2011-04-27 106 views
2

看看下面的代码:线程安全类和方法参数

public void SomeMethodWithParameters(MutableObject mutableParameter, String stringParameter, double structParameter) 
    { 
     // some code 
    } 

这是我的理解,这个代码是不是线程安全的,由于这样的事实,mutableParameter是这种方法的多变之外。

你在代码中使用什么策略(除了只使用不可变的类或结构作为参数)以防止这种可能性?是否所有传递的对象都是这个方法实际上是深层克隆?

+0

在C#中,我认为“参考参数”的通常含义是'ref'参数。也许“参考类型的参数”会更清楚? – recursive 2011-04-27 21:20:31

+0

这只是一个问题*如果* mutableParameter *可以*在方法调用期间更改。如果没有其他线程具有对mutableParameter的引用,那么在方法外部更改它并不重要,因为它不会更改... – forsvarir 2011-04-27 21:21:36

+0

为了论证的缘故,它*在方法调用之外是可修改的。 – miguel 2011-04-27 21:27:57

回答

9

这是我的理解,这个代码是不是线程安全的,因为mutableParameter在此方法之外是可以改变的。

澄清:的内容的可变“mutableParameter”是不会改变的;该变量将在其整个生命周期中引用相同的实例(前提是您不要在方法中更改它)。被引用的实例所拥有的变量的内容可能会改变,如果其他有相同对象的引用的其他线程正在改变它们。

你在代码中使用什么策略(除了只使用不可变类或结构作为参数)以防止这种可能性?

如果可能,请完全避免此问题。不要首先在多个线程上读取和写入同一对象的相同变量。

如果你无法避免它,那么创建一个适当可访问的锁定对象。

定义一个锁定协议,以便您承诺在访问任何可以在另一个线程上访问的变量之前锁定该对象。完成后解锁。

  • 请确保订购您的锁以防止死锁。
  • 锁定对象应尽可能无法访问。私人比内部更好,内部更好,比公共更好。切勿选择类型作为锁对象;你无法控制谁按照什么顺序锁定它,因此你有可能陷入僵局。
  • 确保访问变量线程遵循协议。无论如何锁定100个通道中的99个并且没有锁定地将第100个锁定在任何位置都没有用。如果你不能防止你不能控制访问资源的代码,那么资源本身需要重写成线程安全。
  • 衡量你的表现,看看锁的竞争频率。如果锁被严重争夺,请更改您的架构以防止争用。只有当你绝对肯定地有一个严重的问题,如果你尝试一种无锁或低锁解决方案,你无法以其他方式改善。
+0

了解内容与参考本身。 – miguel 2011-04-27 21:21:22

+0

但是如果您传递给方法的类参数也可以从另一个类中修改,那么如何确保您锁定在同一个对象实例上(无静态) – miguel 2011-04-27 21:27:16

+1

@miguel:现在您知道为什么写这么难正确的多线程代码!你必须设计一个适用于你所面对的具体情况的协议。你如何做到这一点取决于你。 – 2011-04-27 21:29:00