Java中处理同步块/方法中异常的最佳实践

Java中处理同步块/方法中异常的最佳实践,java,multithreading,synchronization,Java,Multithreading,Synchronization,我已经读到,在编码同步块或方法时必须小心,因为如果线程因为异常而退出同步方法/块,那么同步锁将被释放,因为内存模型不太关心线程是否因为异常而退出。因此,即使对象可能处于损坏状态,其他线程也可以获取同步锁 P>因此,如果我们考虑最佳实践,是否有任何可以遵循的准则来编写同步方法/块。我个人认为锁非常好,因为它们的try{}finally{}语义,但是如果我们有一个API,它需要绝对同步的方法/块,那么编码这些同步的方法/块的好方法是什么呢。我认为对于同步方法也可以使用try-finally方法,但

我已经读到,在编码同步块或方法时必须小心,因为如果线程因为异常而退出同步方法/块,那么同步锁将被释放,因为内存模型不太关心线程是否因为异常而退出。因此,即使对象可能处于损坏状态,其他线程也可以获取同步锁

<> P>因此,如果我们考虑最佳实践,是否有任何可以遵循的准则来编写同步方法/块。我个人认为锁非常好,因为它们的try{}finally{}语义,但是如果我们有一个API,它需要绝对同步的方法/块,那么编码这些同步的方法/块的好方法是什么呢。我认为对于同步方法也可以使用try-finally方法,但是StringBuffer类不使用这种方法。我不确定是否有任何具有同步方法的标准类使用这种方法。那么,将日志记录部分留给一个uncaughtExceptionHandler应该是一条出路吗

有没有其他好的实践可以派上用场?如果对象的状态损坏,是否有方法防止其他线程获取同步锁。UncaughtExceptionHandler和finally块最多只能执行额外的日志记录。是这样吗?它们不能真正阻止其他线程随后获取同步锁。是这样吗?那么,我们应该如何用Java编写同步方法/块呢?

关键部分(也称为“同步块”)可能对应用程序的性能非常有害。了解阿姆达尔定律。每次你开始写“synchronized”时,你应该问自己,“我可以重新设计以消除需求吗?”†如果答案是否定的,那么你的下一个问题应该是,“我如何使它尽可能小?”

如果同步块中的代码可以抛出异常,那么它可能不会尽可能小。找到一种在不接触全局状态的情况下执行异常抛出操作的方法,然后仅在异常抛出操作产生有效结果时输入synchronized块来修改状态

如果听起来像是我要你写一个做额外工作的程序,那是因为我要你写一个做额外工作的程序。阿姆达尔定律的信息是,为了从多处理器机器中获得最佳性能,我们通常不得不以一种在单处理器机器上不太理想的方式来做事情

多处理已经存在了一段时间,但多处理体系结构的广泛部署是新的。人们仍在使用“多处理器”是指“超级计算机”时编写的书籍。但突然之间,我们有了四核和八核的笔记本电脑,甚至手机也有多核

是时候停止老办法了



†java.util.concurrent类是你的朋友。

你能举个例子吗?如果由于抛出的异常而释放了锁,为什么要防止其他线程获取锁?这个问题对于StackOverflow来说太广泛了。一个好的答案应该是书中的一两章,因为异常可能导致对象处于损坏状态。例如,让我们假设我有一个同步的方法借记一个帐户。假设有一些运行时异常未被破坏。线程死机,UncaughtExceptionHandler将其记录下来。但现在另一个线程尝试再次执行借记或贷记。它会得到锁的。我想我无法阻止这种情况发生,但我不确定。我知道我可以进行日志记录。但这就是我所能做的。从最佳实践的角度来看,我的问题是一般性的——我们是否应该在try-finally块中对逻辑进行编码。您应该阅读。异常不应使对象处于不一致的状态。从根本上说,这就是try/catch的作用。发生异常时,catch/finally逻辑负责恢复一致状态。