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();
}
}
}
我理解在读取情况下使用成语:如果在read方法中抛出异常,其他线程仍然可以读/写一致资源。但是如果在write方法中抛出的excteption读取方法可以读取不一致的资源。
为什么读取不一致的值比无限锁等待更合适? 为什么Java库作者更喜欢这种行为?
答案 0 :(得分:0)
你在这里混淆了不同的概念。有:
关键点:这两者基本上是正交的。你正在解决其中一个问题的事实并没有为你神奇地解决另一个问题!
即使你看看你自己的例子,你也会发现你在那里试了一下。但那里没有 catch ! 尽一切代价 含义:如果抛出某个异常,仍会抛出该异常,并且一些捕获者将不得不处理它。
换句话说:如果你的“锁定”代码可以遇到异常,那么你有责任以最有意义的方式处理它。
并且,从“系统”视图:当您获得无限期锁定时,迟早会降低整个系统的性能。如果您遇到一次该异常,那么您将更频繁地遇到它。所以,很可能你很快就会用完线程/锁;并且您的整个申请将受到影响。这正是可以解决分布式基础架构的问题 - 一个组件停止处理传入的请求。
长话短说:无限锁等待是你要防止的,因为它会严重影响你的应用程序运行的能力!
最后:当然,这是关于不同要求的平衡。但是,例如:假设您的在线商店丢失了您刚刚从购物车中删除商品的信息。是的,这对客户来说很烦人。但比较一下:整个在线购物应用程序停止处理请求;因为锁定问题。哪个问题会伤害您的业务?
答案 1 :(得分:0)
您可以回滚或向用户提供一些警告信息,但如果程序被阻止,则无法执行任何操作。
我同意你所谈论的data consistency
。在没有任何回滚操作或警告的情况下解锁最终部分是危险的。