2011-03-09 53 views
1

可以说我有一个类有两种方法calculateBonus(Account a)calculatePenalty(Account a)澄清同步

比方说,我将​​关键字添加到方法中,或者在方法内部有synchronized(this)块。这是否意味着如果线程正在计算账户奖励,其他线程在奖金完成之前无法计算其他账户的罚款?

处罚和奖金是多种多样和复杂的,有可能一个帐户可能会同时收到两个帐户。它们的计算顺序无关紧要(有一个截止日期,所以不会影响另一个的结果),但重要的是我不要同时在同一个账户上计算两者(对于明显的数据一致性原因,每种方法内部都会更新状态和审计跟踪信息)。

什么是设计我的代码的最佳方式,以便我可以安全地最大化并行处理?

我也考虑过,到目前为止这些选项:

1)将计算在不同类别的奖金和惩罚的代码,并使用该方法​​关键词。不要喜欢这个想法,因为有一些共享的复杂功能,我想保持在一起,它们不是IO界限,并且执行速度很快,所以不会影响性能。

2)同步通过Account参数。如果我正确理解这一点,那意味着我无法计算另一个线程中执行的另一个帐户的奖金,直到在第一个线程的第一个帐户上计算奖金。但我可以在另一个线程中计算另一个帐户的罚款 - 只是不是相同的帐户。我最喜欢这个,但想确保我理解正确。

3)为每个要同步的方法创建一个内部私人锁定对象,一个用于奖励,另一个用于处罚。如果正确理解这意味着一次只有一个线程可以计算奖金,但它不会不会阻止另一个线程同时计算相同帐户的处罚。

现在我明白我必须小心避免死锁,我打算确保任何同步块内部都不依赖于对其他同步方法的调用。我还打算确保影响最终值的计算中使用的任何局部变量都在synchronized块内。

回答

6

我认为,选择2 - 或它的变体 - 是您最好的选择,但我觉得你还是误解稍微:

同步在帐户传入的参数。如果我正确理解这一点,那意味着我无法计算另一个线程中执行的另一个帐户的奖金,直到在第一个线程的第一个帐户上计算奖金。

没有 - 这意味着:

  • 您将无法计算或者奖金相同帐户一个点球,因为你的线程持有监视器帐户。
  • 任何线程都可以计算奖金或不同帐户的罚款,因为这将有不同的监视器。

现在通常我不喜欢锁定任何公开可见的引用(例如Account参数),因为它使得更难推理锁定。每个Account实例通常最好具有其自己的仅用于锁定的对象,例如,

private final Object lock = new Object(); 

并为Account实例方法来锁定该...但如果你不能把方法Account,你不能真正做到这一点。也许这些方法应该Account虽然?也许你应该改变责任 - 让你有Account.calculateBonus(BonusFormula)Account.calculatePenalty(PenaltyFormula)或类似的东西?

很难说肯定不知道更多的细节,但它一般感觉像只应该知道正在执行同步的对象的锁。

+0

男的你快!我发布后4分钟回复!那么这是否意味着两个或更多的线程可以同时计算不同账户的奖金?因为如果其他线程可以跳入,我有局部变量保存信息会改变这些值,当第一个线程恢复时,它将处理损坏的数据。我怎样才能避免这种情况? – BigMac66 2011-03-09 17:55:08

+1

@ BigMac66:如果您锁定某个对象,则同时锁定此对象的任何内容都可以完成。局部变量对于方法的每个调用都是本地的,因此其他线程不会改变它们。 – 2011-03-09 17:57:57

+0

@ BigMac66:是的,不同的线程可以同时计算奖金......但是*线程之间不共享* local *变量。 (当然,如果不同线程中的这些局部变量引用修改相同的对象,那么你可能会遇到问题。) – 2011-03-09 17:58:15