本节将介绍不使用同步化机制所产生的问题。下一节将介绍如何同步地访问对象。
在下面的试验程序中,模拟了一个有10个账户的银行。银行随机地在这10个账户间进行现金交易。本程序设计两个类Bank和Customer,共有10个线程。一个线程对应一个账户。每次交易将把一笔随机数量的现金从一个账户转移到另一个随机产生的账户。我们用Bank类的transfer()方法来实现现金交易。它把一定数量的现金从一个账户转移到另一个账户。如果源账户中没有足够现金,那么transfer()方法将直接返回,不执行任何交易。Bank类的transfer()方法的源代码如下所示:
在Customer类中,run()方法不断地从一个指定的银行账户取出一定数量的现金。在每个循环中,run()方法首先随机地选取一个目标账户和产生不超过$1000的随机数量的交易现金,接着调用Bank类对象的transfer()方法来进行现金转移。
在这个模拟程序运行过程中,我们不知道任何一个账户在某一时刻的现金数量,但是我们知道这10个账户的现金总额应保持不变,因为我们只是把一定数量的现金从一个账户转移到另一个账户,而没有取走。如图9-5所示,10个账户Account0~Account9,每个账户都有$100000,总金额Total Amount为$1000000。但是当单击“Restart”按钮,开始进行交易121次,单击“Stop”按钮后,显示的总金额Total Amount是$984851。总金额Total Amount小于$1000000,出现了错误。总金额怎么会少了呢?少了钱哪里去了?请读者思考。
图9-5 10个账户的初始状态
下面的程序例9-5给出了这个程序的全部源代码,仔细研究一下其代码,找出代码中的问题。
【例9-5】线程不同步产生的错误。
(www.xing528.com)
上述程序还需要Customer类,放在另一个文件Customer.java中。
运行程序,将产生如图9-6和图9-7所示的结果。这表明多线程程序在某些情况下,不使用同步会产生严重错误。出现错误的原因是在交易线程from与into之间,插进了其他线程的交易,从而进与出不同步。读者不妨将方法transfer(int from,int into,int amount)中“先减后加”改为“先加后减”,其交易结果,总金额会多出钱来。其解决的办法就是让Java的线程同步执行。
图9-6 总金额出现错误一
图9-7 总金额出现错误二
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。