黑马程序员技术交流社区

标题: 多线程的安全问题之锁 [打印本页]

作者: 谢冬    时间: 2013-3-17 13:41
标题: 多线程的安全问题之锁
/*模拟银行取钱*/
  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或者其他对象作为锁的时候,为什么共享数据会出错?毕老爷说着个同步代码块的锁可以任意指定,我反复模拟了几个列子,都会出错,只有使用要操作的对象时作为锁时,测试结果才没问题

作者: 谢波    时间: 2013-3-17 14:35
线程同步加锁,一定要明确要操作的是共享数据是什么
只针对 操作共享数据的代码加锁
你的例子中,共享数据是balance 所以锁应该加在drawBalance和getBalance这两个方法上
在这两个方法上用this或者其他的锁是可以的
当你把锁加在两个线程中时,也是可以的
但是,无论在什么时候都必须保证锁对象是唯一的,也就是说要是同一把锁
如果用this,那么你总共创建了两个DrawThread对象,this代表的是对象本身,所以这时的两个this是不相等,不是同一把锁
用其他的对象作为锁也是一个道理,只要保证锁对象唯一就ok了
比如说,可以建立一个类 a 里面定义一个对象 public static Object lock= new Object();然后用这个lock作为他们的锁,都是可以的
作者: 罗威    时间: 2013-3-17 16:30
通俗点说就是:
new DrawThread("A账户:", a, 500).start();你new一次就创建了第一个对象

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

this表示本类对象的引用,你创建了两个对象,每个对象都有一个不同的this锁,就说明你有两把锁了,当然就会出错  你想通了没?有什么问题可以继续追问!
作者: 陈丽莉    时间: 2013-3-17 19:34
若还有问题,请继续追问;  没有的话,请将帖子分类改成【已解决】~




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2