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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张晋瑜 中级黑马   /  2013-2-21 13:41  /  2027 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 zhangjinyu1991 于 2013-2-21 13:51 编辑

这是我看书上的一个存钱取钱的代码,至今都没明白为什么老是要在操作临界资源动作的前后加上强制线程切换,sleep()方法不是不释放锁吗,既然不释放锁,虽然线程暂停有什么用?为什么要强制转换线程?这样有什么好处?搞不懂!!
  1. public class TakeSavingMoney {

  2.         /**
  3.          * @param args
  4.          */
  5.         public static void main(String[] args) {
  6.                 // TODO Auto-generated method stub
  7.                 Account account=new Account("晋瑜", 5000000);
  8.                 // 存入1000000
  9.                 (new Saver(account, 1000000)).start();
  10.                 // 取出30000
  11.                 (new Fetcher(account, 30000)).start();
  12.                 // 取出450000
  13.                 (new Fetcher(account, 450000)).start();
  14.                 // 存入50000
  15.                 (new Saver(account, 50000)).start();
  16.         }

  17. }
  18. class Account{        // 账户类
  19.         private String name;        // 账户名
  20.         private double money;        // 账户余额
  21.         
  22.         public Account(String name, double money) {
  23.                 // TODO Auto-generated constructor stub
  24.                 this.name=name;
  25.                 this.money=money;
  26.         }
  27.         public String getName(){
  28.                 return this.name;
  29.         }
  30.         public double getMoney(){
  31.                 return this.money;
  32.         }
  33.         public void put(double money){        // 存钱
  34.                 this.money+=money;
  35.         }
  36.         public void get(double money){        // 取钱
  37.                 this.money-=money;
  38.         }
  39. }

  40. class Saver extends Thread{        //存钱类
  41.         private Account account;        // 存钱人拥有一个账户
  42.         private double money;                // 将要存钱的数
  43.         public Saver(Account account, double money) {
  44.                 // TODO Auto-generated constructor stub
  45.                 this.account=account;
  46.                 this.money=money;
  47.         }
  48.         @Override
  49.         public void run() {
  50.                 // TODO Auto-generated method stub
  51.                 synchronized (account) {        // account是临界资源
  52.                         //临界区
  53.                         System.out.println(account.getName()+"账户\n"+"现有:"+account.getMoney()+"元\n"+"存入:"+this.money+"元.");
  54.                         try {                // 旨在强制发生线程切换
  55.                                 sleep(1);
  56.                         } catch (InterruptedException e) {
  57.                                 // TODO Auto-generated catch block
  58.                                 e.printStackTrace();
  59.                         }
  60.                         account.put(this.money);
  61.                         try {
  62.                                 sleep(1);
  63.                         } catch (InterruptedException e) {
  64.                                 // TODO Auto-generated catch block
  65.                                 e.printStackTrace();
  66.                         }
  67.                         System.out.println("现有余额:"+account.getMoney());
  68.                 }
  69.         }
  70. }

  71. class Fetcher extends Thread{        //取钱类
  72.         private Account account;        // 取款人持有一个账户
  73.         private double money;                // 将要取钱的数
  74.         public Fetcher(Account account, double money) {
  75.                 // TODO Auto-generated constructor stub
  76.                 this.account=account;
  77.                 this.money=money;
  78.         }
  79.         @Override
  80.         public void run() {
  81.                 // TODO Auto-generated method stub
  82.                 synchronized (account) {        
  83.                         //临界区
  84.                         System.out.println(account.getName()+"账户\n"+"现有:"+account.getMoney()+"元\n"+"取出:"+this.money+"元.");
  85.                         try {
  86.                                 sleep(1);
  87.                         } catch (InterruptedException e) {
  88.                                 // TODO Auto-generated catch block
  89.                                 e.printStackTrace();
  90.                         }
  91.                         account.get(this.money);
  92.                         try {
  93.                                 sleep(1);
  94.                         } catch (InterruptedException e) {
  95.                                 // TODO Auto-generated catch block
  96.                                 e.printStackTrace();
  97.                         }
  98.                         System.out.println("现有余额:"+account.getMoney());
  99.                 }
  100.         }
  101. }
复制代码

3 个回复

正序浏览
胥文 发表于 2013-2-21 19:22
sleep()是释放CPU资源,但是不释放锁
个人觉得用sleep的原因如下:
1,在同步代码块中加Sleep是为了更好的 ...

听起来挺有道理,其实我试过不用sleep()去强制切换其实运行结果也是正确的;
就是不知道以后要是写程序时都不用sleep()进行强制切换会不会造成什么严重后果?
因为我看到好几本书上人家作者都会去用sleep()强制切换,这样到底有什么好处?
回复 使用道具 举报
sleep()是释放CPU资源,但是不释放锁
个人觉得用sleep的原因如下:
1,在同步代码块中加Sleep是为了更好的让程序员学习者理解cpu在切换
2,让线程切换来模拟现实情况看有什么异常发生,好在调试阶段就把问题就找出来
以免程序到用户那边出了问题就不好了

评分

参与人数 1黑马币 +12 收起 理由
张晋瑜 + 12 赞一个!

查看全部评分

回复 使用道具 举报

回帖奖励 +6

   synchronized (account) {        // account是临界资源

55.                        //临界区

56.                        System.out.println(account.getName()+"账户\n"+"现有:"+account.getMoney()+"元\n"+"存入:"+this.money+"元.");

57.                        try {                // 旨在强制发生线程切换

58.                                sleep(1);


你说的是这里吗?
线程中 cpu做快速切换,以达到同时运行的结果,但是cpu切换的时候是不固定路线的。所以你不做强制发生线程转换的话,会很有可能发生并发现象,或者是先打印下面的代码然后再回头打印上面的代码。  然后就会发现存入的钱和余额不相等。
做 sleep之后代码就从上往下一一打印,这就是为什么要强制发生线程转换的原因。

愚见,请忽略。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马