A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 谢冬 中级黑马   /  2013-3-17 13:41  /  1190 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

/*模拟银行取钱*/
  1. public class Account {
  2.         //账户余额
  3.         private double balance;
  4.         public Account(double balance) {
  5.                 this.balance = balance;
  6.         }
  7.         /*取钱的方法*/
  8.         public double drawBalance(double drawBalance)
  9.         {
  10.                 balance = balance - drawBalance;
  11.                 return balance;
  12.         }
  13.         /*查询余额*/
  14.         public double getBalance()
  15.         {
  16.                 return balance;
  17.         }
  18. }
复制代码
/*取钱的线程*/
public class DrawThread extends Thread
{
        private Account a;
        //要取的金额
        private double drawBalance;
        public DrawThread(String name, Account a, double drawBalance)
        {
                super(name);
                this.a = a;
                this.drawBalance = drawBalance;
        }
        public void run()
        {
                while(true){
                        synchronized(a){
                                if(a.getBalance() < drawBalance){
                                        System.out.println(Thread.currentThread() + " : 余额不足,当前余额: " + a.getBalance());
                                        break;
                                }
                                try {
                                        Thread.sleep(10);
                                } catch (InterruptedException e) {
                                        e.printStackTrace();
                                }
                                a.drawBalance(drawBalance);
                                System.out.println(Thread.currentThread() + "取钱成功,取走金额:" + drawBalance + " ,当前余额:" + a.getBalance());
                        }
                }
        }
}
/*在主方法中运行*/
  1. public class DrawTest {
  2.         public static void main(String[] args) {
  3.                 Account a = new Account(1000);
  4.                 new DrawThread("A账户:", a, 500).start();
  5.                 new DrawThread("B账户:", a, 300).start();
  6.         }
  7. }
复制代码
//当使用this或者其他对象作为锁的时候,为什么共享数据会出错?毕老爷说着个同步代码块的锁可以任意指定,我反复模拟了几个列子,都会出错,只有使用要操作的对象时作为锁时,测试结果才没问题

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

3 个回复

倒序浏览
线程同步加锁,一定要明确要操作的是共享数据是什么
只针对 操作共享数据的代码加锁
你的例子中,共享数据是balance 所以锁应该加在drawBalance和getBalance这两个方法上
在这两个方法上用this或者其他的锁是可以的
当你把锁加在两个线程中时,也是可以的
但是,无论在什么时候都必须保证锁对象是唯一的,也就是说要是同一把锁
如果用this,那么你总共创建了两个DrawThread对象,this代表的是对象本身,所以这时的两个this是不相等,不是同一把锁
用其他的对象作为锁也是一个道理,只要保证锁对象唯一就ok了
比如说,可以建立一个类 a 里面定义一个对象 public static Object lock= new Object();然后用这个lock作为他们的锁,都是可以的

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
通俗点说就是:
new DrawThread("A账户:", a, 500).start();你new一次就创建了第一个对象

new DrawThread("B账户:", a, 300).start();你再new一次又创建了一个对象

this表示本类对象的引用,你创建了两个对象,每个对象都有一个不同的this锁,就说明你有两把锁了,当然就会出错  你想通了没?有什么问题可以继续追问!

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
若还有问题,请继续追问;  没有的话,请将帖子分类改成【已解决】~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马