【问题标题】:Clarification on synchronization关于同步的说明
【发布时间】:2011-03-09 17:38:53
【问题描述】:

假设我有一个类有两个方法calculateBonus(Account a)calculatePenalty(Account a)

假设我在方法中添加了synchronized 关键字,或者在方法中添加了synchronized(this) 块。这是否实际上意味着如果一个线程正在计算一个帐户的奖金,在奖金完成之前其他线程无法计算另一个帐户的罚款?

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

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

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

1) 将计算奖励和惩罚的代码放在不同的类中,并在方法上使用synchronized 关键字。不喜欢这个想法,因为我想将一些共享的复杂函数放在一起,它们不受 IO 限制并且执行速度很快,因此不会影响性能。

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

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

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

【问题讨论】:

    标签: java concurrency synchronization parallel-processing


    【解决方案1】:

    我认为选项 2 - 或它的变体 - 是您最好的选择,但我认为您仍然稍微误解了它:

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

    不 - 这意味着:

    • 您将无法计算相同帐户的奖金罚金,因为您的线程正在为该帐户持有监视器。
    • 不过,任何线程都可以计算不同帐户的奖金或罚款,因为该帐户会有不同的监视器。

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

    private final Object lock = new Object();
    

    例如Account 中的方法来锁定它...但如果你不能将方法放在Account 中,你就不能真正做到这一点。也许这些方法应该Account 中?或许你应该改变责任——让你拥有Account.calculateBonus(BonusFormula)Account.calculatePenalty(PenaltyFormula) 或类似的东西?

    如果不知道更多细节很难确定,但通常感觉锁应该只有执行同步的对象知道。

    【讨论】:

    • 伙计,你很快!你在我发帖后 4 分钟回复了!那么这是否意味着两个或多个线程可以同时计算不同帐户的奖金?因为我有保存信息的局部变量,如果另一个线程可以跳转,它会改变这些值,当第一个线程恢复时,它会处理损坏的数据。我怎样才能避免这种情况?
    • @BigMac66:如果您锁定某个对象,那么同时锁定该对象的任何操作都无法完成。局部变量对于方法的每次调用都是局部的,因此不会被其他线程更改。
    • @BigMac66: 是的,不同的线程可以同时计算奖金……但是本地变量不会在线程之间共享。 (当然,如果这些局部变量在不同的线程中引用一个修改相同的对象,那么你可能会遇到问题。)
    • 有趣的是我可以查看正在进行的答案,我上面的评论是基于你不完整的答案,因为我现在看到的不同。
    • @BigMac66:这是我最初提交的答案,然后我对其进行了编辑。
    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多