Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java尝试最终解锁习惯用法_Java_Multithreading_Locking_Try Finally - Fatal编程技术网

java尝试最终解锁习惯用法

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

Javadoc和一些answers()声明:

在大多数情况下,应使用以下习语:

 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。如果线程发出警告,但没有解锁它拥有的锁,它将阻止其他线程。比如这个例子:我不知道你所说的“它无论如何都没有被阻止”是什么意思。我认为这是不相关的比较。你可以发现你账户上的钱不见了,或者你发现它被冻结了一段时间。