zoukankan      html  css  js  c++  java
  • 黑马程序员——多线程中的安全问题 :

    ---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------


    /*建立一个银行类,银行中有一个金库sum,银行类中有add()方法,
     * 向其中加钱,每次加钱数量为n
     */
    class Bank {
        private int sum;
        public void add(int n) {
            sum += n;
            System.out.println(Thread.currentThread().getName()+"  sum = "+sum);
        }
    }
    
    class Cus implements Runnable {
        private Bank b = new Bank();
        public void run() {
            for(int i=0;i<3;i++) {
                b.add(100);
            }
        }
    }
    
    class Test {
        public static void main(String args[]) {
            //两个储户同时操作同一个储蓄账户中的资金
            Cus c = new Cus();
            new Thread(c).start();
            new Thread(c).start();
        }
    }
    复制代码

    上面程序运行结果出现了如下结果,

    Thread-1 sum = 200
    Thread-1 sum = 300
    Thread-1 sum = 400
    Thread-0 sum = 400
    Thread-0 sum = 500
    Thread-0 sum = 600

    这是一个什么运行结果导致的呢?

    分析:1、打印出来的账单中可以看到,开始就以200出现,而不是100,这是由于线程0先调用了add()方法执行sum += n,

    此时,账户sum中的资金就是100,就在此时并没有打印sum,线程执行权被线程1获得,线程1调用add()方法,因为

    两储户同时操作同一账户(数据共享),账户中已有100再储存100就有200。

      2、打印结果中有两个400,这是因为线程1获得执行权后,开始向其账户中存钱,存完后,线程0获得执行权,线程0

    继续上一次未完成的造作打印账户信息,而此时账户中的资金信息已经是线程1操作完的结果sum=400,所以打印出了连续

    两个相同的信息。

      ★★★从上面的输出结果中很明显的看出这个由两个储户同时存钱的多线程中存在着线程的安全问题★★★

      为了解决这一线程安全问题的产生要明确:

      1、哪些是共享数据

      2、哪些语句操作共享数据

    问题的产生是由于多个线程同时进入操作共享数据语句所产生的,为了不让多个线程同时进入某一代码片段,加入synchronized

    同步代码块关键字。

      修改后代码:

    复制代码
    /*建立一个银行类,银行中有一个金库sum,银行类中有add()方法,
     * 向其中加钱,每次加钱数量为n
     */
    class Bank {
        private int sum;
        Object obj = new Object();
        public void add(int n) {
            synchronized(obj) {  //★★★
            sum += n;
            System.out.println(Thread.currentThread().getName()+"  sum = "+sum);
            }
        }
    }
    
    class Cus implements Runnable {
        private Bank b = new Bank();
        public void run() {
            for(int i=0;i<3;i++) {
                b.add(100);
            }
        }
    }
    
    class Test {
        public static void main(String args[]) {
            //两个储户同时操作同一个储蓄账户中的资金
            Cus c = new Cus();
            new Thread(c).start();
            new Thread(c).start();
        }
    }
    复制代码

      输出结果:

    Thread-0 sum = 100
    Thread-1 sum = 200
    Thread-1 sum = 300
    Thread-1 sum = 400
    Thread-0 sum = 500
    Thread-0 sum = 600

    ---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------
    用心-细心-专心-决心 学习就像爬大山,一步一步向前走 -态度决定高度-
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 黑色星期五
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    控件动态产生器(使用RegisterClasses提前进行注册)
    Delphi编写自定义控件以及接口的使用(做了一个TpgDbEdit)
    Log4delphi使用心得
  • 原文地址:https://www.cnblogs.com/xianyou-liang/p/8503372.html
Copyright © 2011-2022 走看看