java try finally unlock 成语
Posted
技术标签:
【中文标题】java try finally unlock 成语【英文标题】:java try finally unlock idiom 【发布时间】:2016-12-05 16:12:28 【问题描述】:Javadoc 和一些答案 (Threads - Why a Lock has to be followed by try and finally) 指出:
在大多数情况下,应使用以下成语:
Lock l = ...;
l.lock();
try
// access the resource protected by this lock
finally
l.unlock();
我在标准 Java 库中看到了这种习惯用法的示例。 这是我使用它的例子。字段 acc1 和 acc2 代表银行帐户的一个众所周知的示例。主要约束是 acc 的值的总和 - 它应该是 0。
public class Main
int acc1;
int acc2;
ReadWriteLock lock = new ReentrantReadWriteLock();
public int readSum()
lock.readLock().lock();
try
return acc1 + acc2;
finally
lock.readLock().unlock();
public void transfer()
lock.writeLock().lock();
try
acc1--; // constraint is corrupted
// exception throwed here
acc2++; // constraint is regained
finally
lock.writeLock().unlock();
我理解在读取情况下使用成语:如果在读取方法中抛出异常,其他线程仍然可以读取/写入一致的资源。但是如果在写方法中抛出异常,读方法可以读取不一致的资源。
为什么读取不一致的值比无限锁等待更可取? 为什么 Java 库的作者更喜欢这种行为?
【问题讨论】:
锁提供了某些形式的事务行为(例如一致的数据视图)。但是,它们不提供回滚功能。你要么需要自己实现,要么使用数据库。 当您的软件运行一个每天处理价值数百万美元业务的商业网站时,如果它对 I/O 错误做出反应而永远挂起,您的客户将不会高兴。 (别问我怎么知道的!) PS:@GhostCat 的回答谈到了罗伯特(“鲍勃叔叔”)马丁所说的关注点分离——这个想法是,如果你让一团代码负责为了解决两个或多个不同的问题(例如,锁定和错误处理),当需求发生变化时,它将变成未来维护的噩梦。查看鲍勃叔叔的书:amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/… @james large IOException 已检查,这对您来说并不奇怪。你应该抓住它,回滚资源状态,然后调用解锁。但是如果在 ConcurrentHashMap.put 方法中抛出 OutOfMemoryError ,它只会解锁 map 并允许其他线程使用损坏的 hashMap。 当我收到 OOME 时,我希望服务被拒绝,但不是数据损坏。 【参考方案1】:您可以回滚或向用户提供一些警告信息,但如果程序被阻止,您将无能为力。
我同意你所说的data consistency
。在没有任何回滚操作或警告的情况下解锁 finally 部分是很危险的。
【讨论】:
抛出异常的线程可以给出一些警告。无论如何它都没有被阻止。 @user3517035。如果线程发出警告但没有解锁它拥有的锁,它将阻塞其他线程。比如这个例子:***.com/a/6950124/3378204I 不知道你说的“反正没有被屏蔽”是什么意思。【参考方案2】:您在这里混淆了不同的概念。有:
-
锁定,防止死锁,然后
另一个维度,我们称之为“数据完整性”。
要点:这两者基本上是正交的。您正在解决其中一个问题并不能神奇地为您解决另一个问题!
即使您查看自己的示例,也会发现您在那里放置了 try/finally。但是那里没有catch! 不惜一切代价 含义:如果抛出一些异常,该异常仍然被抛出,并且一些捕手将不得不处理它。
换句话说:如果您的“锁定”代码可能会遇到异常,那么您有责任以最有意义的方式处理它。
而且,从“系统”的角度来看:当您获得无限期锁定时,迟早会降低整个系统的性能。如果您遇到该异常一次,那么您将更频繁地遇到它。所以,很有可能你很快就会用完线程/锁;你的整个应用程序都会受到影响。这正是可以破坏分布式基础设施的问题——一个组件停止处理传入的请求。
长话短说:无限锁等待是您要防止的,因为它会严重影响您的应用程序的运行能力!
最后:当然,这是关于不同需求的平衡。但是,例如:假设您的在线商店丢失了您刚刚从购物车中删除商品的信息。是的,这对客户来说很烦人。但是比较一下:整个在线购物应用程序停止处理请求;因为锁定问题。哪个问题会对您的业务造成更大的伤害?
【讨论】:
我认为这是不正确的比较。您可以发现您帐户中的钱已经消失,或者您发现它被冻结了一段时间。以上是关于java try finally unlock 成语的主要内容,如果未能解决你的问题,请参考以下文章