繁体   English   中英

CoreJava 第 11 版关于客户端锁定(同步块)的线程问题

[英]CoreJava 11th Ed Threading question on client-side locking (synchronized block)

我正在阅读以下关于为什么不建议使用客户端锁定的部分,如下所示:

“有时,程序员使用对象的锁来实现额外的
原子操作——一种称为客户端锁定的实践。 考虑,对于
例如,Vector 类,它是一个方法同步的列表。
现在假设我们将银行余额存储在 Vector 中。 这是
传输方法的简单实现:

public void transfer(向量账户,int from,int to,int amount)//
{
account.set(from,accounts.get(from) - 金额);
account.set(to, accounts.get(to) + amount);
System.out.println(. . .);
}
Vector 类的 get 和 set 方法是同步的,但是
对我们没有帮助。 线程被抢占是完全有可能的
在第一次调用 get 完成后的 transfer 方法。 其他
然后线程可以将不同的值存储到相同的位置。 然而,我们
可以劫持锁:

公共无效转移(矢量帐户,int from,int to,int金额)
{
同步(帐户)
{
account.set(from,accounts.get(from) - 金额);
account.set(to, accounts.get(to) + amount);
}
System.out.println(. . .);
}

这种方法有效,但它完全取决于 Vector
class 对其所有的 mutator 方法使用内在锁 然而,这是
真的是事实吗? Vector 类的文档没有这样的
承诺。 你要仔细研究源代码,希望以后
版本不会引入不同步的变异器。 如您所见,客户-
侧锁非常脆弱,一般不推荐使用。”

问题:
既然transfer方法中的synchronized(accounts)已经获得了accounts内在锁,那么为什么依赖vector类的所有mutator方法都使用内在锁(如粗斜体突出显示的?

如果accounts Vector的唯一突变发生在transfer方法中,那么Vector同步其突变器就无关紧要了。

但是,通过锁定相同的对象已有的突变方法(即对Vector ),我们防止对其他任何不同诱变操作Vector

这不仅仅是由另一个线程完成的可能破坏我们数据的传输,而是例如,在我们读取余额之后和设置之前在to帐户上执行的存款。

正如 Holger 指出的那样,一旦你在一个线程中发生了变化并在另一个线程中读取,如果你想要数据的一致视图,甚至读取操作也需要同步。

正如Core Java所建议的那样,最好封装您要保护的数据,例如(玩具示例)

public class Accounts {
    private final List<Integer> accounts = new ArrayList();

    public synchronized void transfer(int from, int to, int amount) {
        accounts.set(from, accounts.get(from) - amount);
        accounts.set(to, accounts.get(to) + amount);
    }
    
    public synchronized void deposit(int to, int amount) {
        accounts.set(to, accounts.get(to) + amount);
    }
    
    public synchronized List<Integer> getAccountsSnapshot() {
        // don't return our internal data structure, make a defensive copy
        return new ArrayList(accounts);
    }
}

返回数据的副本执行两个功能:

  • 我们不提供对内部数据的引用,因此客户端无法直接修改ArrayList的值,而无需使用我们提供的 API。
  • 客户端获得账户余额的一致快照,因此他们可以对所有账户求和并获得在他们调用getAccountsSnapshot有效的总数。 否则,他们在计算总和时的修改可能意味着他们得到了“现实生活”中从未发生过的总和。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM