zoukankan      html  css  js  c++  java
  • 线程同步学习一

    线程不安全举例,存钱取钱  账户余额有时为负数。

    package threadStudy;
    
    /**
     * 模拟线程不安全 存钱取钱
     */
    
    public class SynTest1 {
        public static void main(String[] args) {
            Account account = new Account("王五的银行卡", 1000);
            Withdraw withdraw1 = new Withdraw(account, 800);
            Withdraw withdraw2 = new Withdraw(account, 700);
            Thread t1 = new Thread(withdraw1, "husband");
            Thread t2 = new Thread(withdraw2, "wife");
            t1.start();
            t2.start();
        }
    }
    
    // 账户
    class Account {
        private String name;
        private int money;
    
        public Account(String name, int money) {
            this.name = name;
            this.money = money;
        }
    
        public int getMoney() {
            return money;
        }
    
        public void setMoney(int money) {
            this.money = money;
        }
    
    }
    
    // 取钱的线程
    
    class Withdraw implements Runnable {
    
        private Account account;
        private int money;
        private int balance;
    
        public Withdraw(Account account, int money) {
            super();
            this.account = account;
            this.money = money;
        }
    
        @Override
        public void run() {
            if (account.getMoney() - money < 0) {
                return;
            }
            try {
                Thread.sleep(100);  //模拟网络延时
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            balance = account.getMoney() - money;
            account.setMoney(balance);
            System.out.println(Thread.currentThread().getName() + "取了" + money + "---->账户余额为:" + balance);
        }
    
    }

    会出现以上两种结果,都是错误的。


    并发:指同一个对象被多个线程同时操作。

    并发可能会导致数据不一致,存在线程安全等问题。

    解决此问题可以使用synchronized关键字修饰方法(锁的是this对象) 或者 代码块

    如下解决上面的不同步问题  采用的是synchronized代码块  指定要锁的对象是哪个

    package threadStudy;
    
    /**
     * 模拟线程不安全 存钱取钱
     */
    
    public class SynTest1 {
        public static void main(String[] args) {
            Account account = new Account("王五的银行卡", 1200);
            Withdraw withdraw1 = new Withdraw(account, 800);
            Withdraw withdraw2 = new Withdraw(account, 700);
            Thread t1 = new Thread(withdraw1, "husband");
            Thread t2 = new Thread(withdraw2, "wife");
            t1.start();
            t2.start();
        }
    }
    
    // 账户
    class Account {
        private String name;
        private int money;
    
        public Account(String name, int money) {
            this.name = name;
            this.money = money;
        }
    
        public int getMoney() {
            return money;
        }
    
        public void setMoney(int money) {
            this.money = money;
        }
    
    }
    
    // 取钱的线程
    
    class Withdraw implements Runnable {
    
        private Account account;
        private int money;
        private int balance;
    
        public Withdraw(Account account, int money) {
            super();
            this.account = account;
            this.money = money;
        }
    
        @Override
        public void run() {
            if (account.getMoney() <= 0)
                return;
            test();
        }
    
        private void test() { // 同步关键字加在这里 锁不住 因为默认锁的是this对象 此处即Withdraw对象 应该锁accout对象
            synchronized (account) {
                if (account.getMoney() - money < 0) {
                    return;
                }
                try {
                    Thread.sleep(100); // 模拟网络延时
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
                balance = account.getMoney() - money;
                account.setMoney(balance);
                System.out.println(Thread.currentThread().getName() + "取了" + money + "---->账户余额为:" + balance);
            }
        }
    
    }

    推荐使用synchronized代码块  能够实现更细粒度的控制。

  • 相关阅读:
    canvas的基本用法
    h5新增属性
    jquery中遍历
    git版本控制器
    bootstrap-datetimepicker时间插件
    layer.load的使用
    ajax请求json中的数据
    h5中input的request属性提示文字字段
    layUI
    v-show v-if 的使用
  • 原文地址:https://www.cnblogs.com/ustc-anmin/p/11008620.html
Copyright © 2011-2022 走看看