黑马程序员技术交流社区

标题: 关于同步问题 [打印本页]

作者: 李云锋    时间: 2014-4-10 11:15
标题: 关于同步问题
class ThreadDemo4
{
        public static void main(String[] args)
        {
                Consumer c=new Consumer();
                Thread t1=new Thread(c);
                Thread t2=new Thread(c);
                t1.start();
                t2.start();
        }
}
//定义一个银行类
class Bank
{
        private int sum;
        Object obj=new Object();
        public void add(int num){
        sum+=num;
        System.out.println("sum="+num+"..."+Thread.currentThread().getName());
        }
}
//定义一个客户类
class Consumer        implements Runnable
{
        private Bank bank=new Bank();
        public void run(){
        for(int i=0;i<3;i++){
        bank.add(100);    //一次存100,循环3次
        }
        }

}
这个是毕老师讲课的一个小程序:2个人去银行存钱,总共存3次一次存一百,然后打印出银行的总金额
这个程序不安全性的问题是add方法内,如果先执行sum+=num这句话,然后被别的线程抢去执行,就会发生错误(有时候同时输出两个200,但为什么不同时输出两个300或者其他呢),我现在把add内方法改写成System.out.println("sum="+(sum+=num)+"..."+Thread.currentThread().getName());,去掉上面这句,为什么还会出现这种问题?
作者: fufeng    时间: 2014-4-10 21:29
也是可能出现300或者是其他的的,因为cpu在执行的时候是不停的在进程中进行切换的,比如当
  1. sum+=num;
  2. //线程1第二次执行到这里,此时线程2第一次/执行到这里,则num的值就变为了300,然后线程1和线程2执行打印语句就会出现两个300了。当然这具有一定的随机性,因为线程1和线程2获得cpu的执行权是不确定的    System.out.println("sum="+num+"..."+Thread.currentThread().getName());
复制代码

其实你将+=num写在里面和写在外面其实没什么大的区别,
因为sum是共享数据,所以要使用同步代码块
  1. synchronized(Bank.class)
  2. {
  3.       sum+=num;
  4.       System.out.println("sum="+num+"..."+Thread.currentThread().getName());
  5. }
复制代码

让执行该代码时,只能有一个进程执行,执行完了才让其他进程来执行

作者: 李云锋    时间: 2014-4-11 11:20
fufeng 发表于 2014-4-10 21:29
也是可能出现300或者是其他的的,因为cpu在执行的时候是不停的在进程中进行切换的,比如当

其实你将+=num ...

谢谢您的见解
作者: 曹冬明    时间: 2014-4-14 09:56
理论上时可以出现的,400,,500都可能
作者: xiaowei    时间: 2014-5-8 11:38
可能出现两个300




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