java尝试最终解锁习惯用法
Javadoc和一些answers()声明: 在大多数情况下,应使用以下习语:java尝试最终解锁习惯用法,java,multithreading,locking,try-finally,Java,Multithreading,Locking,Try Finally,Javadoc和一些answers()声明: 在大多数情况下,应使用以下习语: Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); } 我在标准Java库中看到过这种习惯用法的例子。 这是我使用它的例子。字段acc1和acc2代表一个众所周知的银行账户示例。主要约束是acc值的总和-它应该是0 public class
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();
}
}
}
我理解在readcase中使用习惯用法:如果read方法中抛出异常,其他线程仍然可以读/写一致的资源。但若写入方法中抛出执行,则读取方法可以读取不一致的资源
为什么读取不一致的值比无限锁定等待更可取?
为什么Java库作者喜欢这种行为?您在这里混淆了不同的概念。有:
最后:当然,这是关于平衡不同需求的。但是,举个例子:假设你的网店丢失了你刚刚从购物车中删除了一个项目的信息。是的,这对客户来说很烦人。但与之相比:整个在线购物应用程序停止处理请求;因为锁定问题。哪个问题对您的业务影响更大 您可以回滚或向用户发出一些警告信息,但如果程序被阻止,您将无能为力
我同意你所说的数据一致性。在没有任何回滚操作或警告的情况下最终解锁是危险的。锁提供了某些形式的事务行为(例如数据的一致视图)。但是,它们不提供回滚功能。你要么自己实现,要么使用数据库。当你的软件运行一个每天交易数百万美元业务的商业网站时,如果你的客户对I/O错误做出永久挂起的反应,他们将不会高兴。(不要问我怎么知道!)附言:@GhostCat的回答谈到了Robert(“Bob叔叔”)Martin所说的关注点分离——如果你让一个代码块负责解决两个或更多不同的问题(例如锁定和错误处理),那么将来当需求发生变化时,它将变成维护噩梦。看看鲍勃叔叔的书:@james large IOException被选中了,这对你来说并不奇怪。您应该捕获它,回滚资源状态,然后调用unlock。但是,如果ConcurrentHashMap.put方法中抛出OutOfMemoryError,则只需解锁map并允许其他线程使用损坏的hashMap。当我得到OOME时,我预期服务被拒绝,但不会出现数据损坏。引发异常的线程会给出一些警告。它仍然没有被阻止。@user3517035。如果线程发出警告,但没有解锁它拥有的锁,它将阻止其他线程。比如这个例子:我不知道你所说的“它无论如何都没有被阻止”是什么意思。我认为这是不相关的比较。你可以发现你账户上的钱不见了,或者你发现它被冻结了一段时间。