对Java核心技术中一段关于线程同步的代码的疑问
《Java核心技术第九版 卷I》的14.5.6 Synchronized Blocks
一节有一段代码:
public void transfer(Vector<Double> accounts, int from, int to, int amount) {
synchronized (accounts) {
accounts.set(from, accounts.get(from) - amount);
accounts.set(to, accounts.get(to) + amount);
}
System.out.println(. . .);
}
这段代码是模拟银行转账的,当多个线程并发地进行转账时,如果不进行同步就会导致账户中的数据出现不一致的情况。所以书里给这段代码加了synchronized
同步。
但是书中这段程序后面还有一句话:
This approach works, but it is entirely dependent on the fact that the Vector class uses the intrinsic lock for all of its mutator methods.
(加了同步之后)这就没问题了,但是这段代码完全依赖于Vector
类是否使用它自己的锁来同步它的修改方法。
问题来了,为什么这样写还要依赖于Vector
是否加锁,以及加锁方式呢?我认为不管Vector
是否是同步的这段代码都没问题。我实际测试了,将Vector
换成非同步的ArrayList
,确实没有任何问题!不知道作者为什么这样说,难道是我哪里理解的不对?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这句话大概是指
synchronized (accounts)
和Vector
中方法的 intrinsic lock(锁this) 使用的锁都是实例对象本身,所以这种写法才有效,要保证使用同一个锁。假设有两个不同的线程类A和B,都持有 accounts 的引用,线程类A启动的线程使用
synchronized (accounts)
加锁进行同步,而线程类B启动的线程没有,直接使用accounts.set
方法进行修改。如果使用 Vector 类,A线程锁了 accounts 对象,B中调用
set
方法时,由于set
方法使用synchronized
修饰,B也需要获取this
,即:accounts 对象的锁,才能修改,A线程释放锁之前B线程是无法执行的。如果使用 ArrayList 类,B不需要获取锁,直接可以进行修改,会导致状态不一致。
accounts
参数是通过方法调用传进来的,很难保证在进行方法调用之前,程序将accounts
对象发布到了其他线程,这样就有可能有其它线程修改他了。所以作者说依赖于Vector
类的同步机制。比如: