关于同步的说明
假设我有一个类,它有两个方法 calculateBonus(Account a)
和 calculatePenalty(Account a)
。
假设我将 synchronized
关键字添加到方法中,或者在方法内有一个 synchronized(this)
块。这是否实际上意味着,如果一个线程正在计算一个帐户的奖金,则在奖金完成之前,其他线程都无法计算另一个帐户的罚金?
处罚和奖金多种多样且复杂,一个帐户可能会同时收到两者。它们的计算顺序并不重要(有一个截止日期,因此一个不会影响另一个的结果),但重要的是我不要尝试同时在同一帐户上计算两者(对于明显的数据)出于一致性原因,每个方法内部都会更新状态和审计跟踪信息)。
设计代码以便我可以安全地最大化并行处理的最佳方法是什么?
到目前为止,我已经考虑过这些选项:
1)将计算奖金和处罚的代码放在不同的类中,并在方法上使用synchronized
关键字。不喜欢这个想法,因为我想将一些共享的复杂函数放在一起,它们不受 IO 限制并且执行速度很快,因此不会影响性能。
2) 同步传入的Account
参数。如果我理解正确,这意味着我无法计算在另一个线程中执行的另一个帐户的奖金,直到在第一个线程中的第一个帐户上计算奖金。但我可以在不同线程中计算不同帐户的罚金 - 只是不是相同帐户。我最喜欢这个,但想确保我理解正确。
3)为我想要同步的每个方法创建一个内部私有锁对象,一个用于奖励,一个用于惩罚。如果理解正确,则意味着一次只能有一个线程计算奖金,但它不会阻止另一个线程同时计算同一帐户上的罚金时间。
现在我明白我必须小心避免死锁,我计划确保任何同步块内没有任何内容依赖于对其他同步方法的调用。我还打算确保计算中使用的影响最终值的任何局部变量都位于同步块内。
Lets say I have a class that has two methods calculateBonus(Account a)
and calculatePenalty(Account a)
.
Lets say I add the synchronized
keyword to the methods or have a synchronized(this)
block inside the methods. Does this effectively mean that if a thread is calculating a bonus on an account no other thread can calculate a penalty on a different account until the bonus is done?
Penalties and bonuses are varied and complex, it is possible that an account may receive both. It does not matter what order they are calculated (there is a cutoff date so one does not affect the outcome of the other) but it is critical that I do not attempt to calculate both on the same account at the same time (for obvious data consistency reasons, there are statuses and audit trail information being updated inside of each method).
What would be the best way to design my code so that I can SAFELY maximize parallel processing?
I have considered these options so far:
1) Put the code that calculates bonuses and penalties in different classes and use the synchronized
key word on the method. Don't like this idea because there are some shared complex functions that I would like to keep together, they are not IO bound and execute quickly so do not impact performance.
2) Synchronize on the passed in Account
parameter. If I understand this correctly that means that I can not calculate a bonus on another account executing in another thread until the bonus is calculated on the first account in the first thread. But I could calculate a penalty on a different account in a different thread - just not the same account. I like this one the most but want to be sure I understand it correctly.
3) Create an internal private lock object for each method that I want to synchronize, one for bonuses and one for penalties. If understand this correctly it means that only one thread can be calculating a bonus at a time but it does not prevent another thread from calculating a penalty on the same account at the same time.
Now I understand that I have to be careful to avoid deadlock, I plan to make sure that nothing inside any synchronized block depends on calls to other synchronized methods. I also intend to make sure that any local variable used in a calculation that affects the final value is inside the synchronized block.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为选项 2 - 或其变体 - 是你最好的选择,但我认为你仍然有点误解它:
否 - 这意味着:
现在,我通常不喜欢锁定任何公开可见的引用(例如 Account 参数),因为这使得推理锁定变得更加困难。通常最好让每个
Account
实例拥有自己的对象,仅用于锁定,例如Account
中的实例方法来锁定该对象...但是如果您不能将方法放入Account
中,你实际上不能这样做。也许这些方法应该位于Account
中?也许您应该更改责任 - 以便您拥有Account.calculateBonus(BonusFormula)
和Account.calculatePenalty(PenaltyFormula)
或类似的东西?在不了解更多细节的情况下很难确定,但通常感觉锁应该只有执行同步的对象知道。
I think option 2 - or a variant on it - is your best bet, but I think you're still misunderstanding it slightly:
No - it means that:
Now typically I don't like locking on any publicly-visible reference (such as the Account parameter) because it makes it harder to reason about the locking. It would normally be preferable for each
Account
instance to have its own object used just for locking, e.g.and for instance methods in
Account
to lock on that... but if you can't put the methods inAccount
, you can't really do that. Perhaps these methods should be inAccount
though? Perhaps you should change the responsibility - so that you haveAccount.calculateBonus(BonusFormula)
andAccount.calculatePenalty(PenaltyFormula)
or something similar?It's hard to say for sure without knowing more details, but it generally feels like the lock should only be known to the object which is performing the synchronization.