zoukankan      html  css  js  c++  java
  • 对synchronized关键字的理解

    先看两个线程同时访问一个对象的例子.

    public class Account {
        private String accountNo;
        private double balance;
        public Account() {
        }
        public Account(String accountNo, double balance) {
            this.accountNo = accountNo;
            this.balance = balance;
        }
    
        public void setAccountNo(String accountNo) {
            this.accountNo = accountNo;
        }
        public String getAccountNo() {
            return this.accountNo;
        }
        public void setBalance(double balance) {
            this.balance = balance;
        }
        public double getBalance() {
            return this.balance;
        }
    }
    public class DrawThread extends Thread {
        private Account account;
        private double drawAmount;
    
        public DrawThread(String name, Account account,
                          double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
    
        @Override
        public void run() {
            if (account.getBalance() >= drawAmount) {
                System.out.println(getName() +
                        "取钱成功!吐出钞票:" + drawAmount);
                account.setBalance(account.getBalance() - drawAmount);
                System.out.println("	余额为: " + account.getBalance());
            } else {
                System.out.println(getName() + "取钱失败!余额不足!");
            }
        }
    }
    public class TestDraw {
        public static void main(String[] args) {
            Account acct = new Account("1234567", 1000);
            new DrawThread("甲", acct, 800).start();
            new DrawThread("乙", acct, 800).start();
        }
    }
    

    类Account有2个成员变量,帐户名字和余额.DrawThread中的取钱逻辑很简单.先判断余额够不够,如果够,正常取钱,不够的话报余额不足.在TestDraw同时开2个线程取钱,这时候可能会有问题,线程甲判断出还能取钱,准备执行account.setBalance时放弃了处理器,线程乙获得了处理器,判断钱够不够.因为之前线程甲还没有修改balance的值,所以认为可以取钱.所以线程乙取了钱,之后放弃处理器.线程甲之前已经判断过可以取钱,就执行取钱逻辑,这时候帐户余额就变成负的了.多次运行该程序,肯定会出现不正常的现象.
    synchronized就是为了解决类似的问题.把DrawThread改成如下形式:

    public class DrawThread extends Thread {
        private Account account;
        private double drawAmount;
        public DrawThread(String name, Account account,
                          double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
        @Override
        public void run() {
            synchronized (account) {
                if (account.getBalance() >= drawAmount) {
                    System.out.println(getName() +
                            "取钱成功!吐出钞票:" + drawAmount);
                    account.setBalance(account.getBalance() - drawAmount);
                    System.out.println("	余额为: " + account.getBalance());
                } else {
                    System.out.println(getName() + "取钱失败!余额不足!");
                }
            }
        }
    }
    

    synchronized (account){}表示锁住account对象,一个对象访问account时,另外一个对象不能访问.这就保证了线程安全.

  • 相关阅读:
    [项目管理]如何写好项目验收材料
    [英语学习]英语高级口译证书考试 备查
    A1042 Shuffling Machine洗牌机器
    B1018锤子剪刀布
    B1012数字分类
    B1008数组元素循环右移问题
    B1046划拳
    B1026 程序运行时间
    B1016部分A+B
    B1011A+B和C
  • 原文地址:https://www.cnblogs.com/zhouyang209117/p/5321978.html
Copyright © 2011-2022 走看看