在并发环境下,ATM如何工作

4
一个简单的例子:
      class Account{
           private String account_name;
           private String password;
           private double balance;

           public synchronized double getBalance(){
                  return balance;
           }
           public synchronized void setBalance(double add){
                  balance += add;
           }
      }

据我理解,获取与对象相关联的锁并不会阻止其他线程访问该对象。它们必须是相同的锁才能防止访问。
所以如果两个人在不同的自动取款机上尝试访问同一账户,那么就会创建这个Account对象的两个不同实例,是吗?这样它就没有被同一个锁保护了,对吗?
假设A人(线程A)试图将钱存入账户,同时B人(线程B)试图获得账户的总余额,那么它是如何工作的呢?它们是否在使用时缓存Account,使得下一个请求进来时会返回同一个Account对象?
4个回答

5

同步方法会锁定对象实例。但是,如果有一个未同步的方法,可能会发生并发访问。

ATM机不会访问您的账户 - 银行服务器会这样做。 ATM机只是客户端。因此,从2个不同的ATM机访问相同的账户将由银行服务器保护,该服务器在其内存/数据库中仅有一个此帐户的实例(可能受某些锁定机制的保护,而不是用Java编写)。


2
虽然我猜这只是一个学术练习,所以锁定的责任可能会落在他的服务器代码上。 - Hovercraft Full Of Eels
如果银行服务器有多个实例,在负载均衡器后面运行会怎样? - Nitish Jain

0

这取决于系统的实现方式。通常你有一个类的实例,每个实例都与一个隐式锁相关联;或者你可以创建一个简单的

private Object lock;

然后每个人(无论是ATM还是银行员工或其他人)都必须显式地获取此锁。归根结底,这取决于系统的设计和实现方式- 锁定原语只是原语而已。设计师/实施者利用它们并在每个组件中适当地利用它们 - 统一加锁。此外,在这种情况下,我会选择使用原子双精度并避免获取潜在的重量级对象锁。


0

我最好的猜测是他们正在使用对象池作为缓存,每当请求到来时,它会通过某些唯一标识符(如账号)在池中搜索特定的对象(账户)。如果存在,则返回引用。否则,它将从持久数据源加载到池中,并创建新引用并返回。因此,即使两个用户(线程)同时尝试访问它,服务器也不会为它们每个人创建两个实例。

其次,如果一个类中有多个同步方法,并且一个线程当前正在执行同步方法,则所有其他线程尝试访问相同对象的任何同步方法都将被阻止(暂停执行),直到第一个线程退出同步方法。


0
根据我的理解,获取与对象关联的锁并不会阻止其他线程访问该对象。它们必须是相同的锁才能防止访问。
没错。如果多个线程尝试获取一个简单的锁,那么只有一个线程将被允许继续执行。锁不一定需要与单个对象关联。您还可以为其他任务创建锁。
所以,如果两个人在不同的ATM上尝试访问同一个账户,那么会创建两个不同的Account对象实例,对吗?所以它们没有使用相同的锁来保护,对吗?假设Person A(Thread A)试图向账户存钱,同时Person B(Thread B)试图获取账户的总余额。这是如何工作的?他们是否在使用期间缓存了Account对象,以便在下一个请求到来时返回相同的Account对象?
有点类似,您所描述的是分布式锁定场景,这是完全不同的情况。正如其他人已经提到的,ATM会将交易发送回银行进行处理,那里的服务器将处理并发问题。

“Locks do not necessarily need to be associated with a single object” 的意思是什么? - peter
按照惯例,您可以将多个对象与一个锁相关联。例如,您可以将一个操作与锁相关联,该操作可能最终修改多个对象。 - BillRobertson42
你是说在一个状态变量上放置一个锁,并在该锁块内修改其他状态变量吗? - peter
多或少。这是一项风险业务,因为您必须确保所有代码都遵循锁定约定。无论何时使用锁来管理并发代码,这都是真实的。有更安全的高级设施可供使用。请查看Clojure或Erlang中的并发机制以获取更多信息。 - BillRobertson42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接