• java 多线程 4 : 同步代码块


    线程安全问题:多线程访问同一数据,容易出现线程安全问题

    经典问题:银行取钱,1.用户名密码登陆,2.输入取款金额,3.判断账户余额是否大于取款金额,4.如果大于,取款成功,如果小于,取款失败。

    public class Account {
        private String account;//账号
        private double balance;//余额
        
        public Account() {
            super();
        }
        public Account(String account, double balance) {
            super();
            this.account = account;
            this.balance = balance;
        }
        public String getAccount() {
            return account;
        }
        public void setAccount(String account) {
            this.account = account;
        }
        public double getBalance() {
            return balance;
        }
        public void setBalance(double balance) {
            this.balance = balance;
        }
    }
    public class DrawThread extends Thread{
        private Account account;//模拟账户
        private double drawMoney;//当前取钱线程想要取的钱数
        public DrawThread(String name , Account account, double drawMoney) {
            super(name);
            this.account = account;
            this.drawMoney = drawMoney;
        }
        
        public void run() {
            if(account.getBalance() >= drawMoney) {
                System.out.println(getName() + "取钱成功!吐出钞票:" + drawMoney);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                account.setBalance(account.getBalance() - drawMoney);
                System.out.println("	余额为:" + account.getBalance());
            }else {
                System.out.println(getName() + "取钱失败!余额不足");
            }
        }
        
        public static void main(String[] args) {
            Account account = new Account("123456" , 1000);
            new DrawThread("A", account, 800).start();
            new DrawThread("B", account, 800).start();
        }
    }

    同步代码块:上面Demo中,两个并发线程在修改Account对象,很容易造成异常;为了解决这样的异常,java支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块,同步代码块的语法:

    synchronized(Obj){
      ...//同步代码块
    }

    任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成之后,该线程会释放对该同步监视器的锁定。
    虽然java程序允许任何对象作为同步监视器,但是同步监视器的目的:是为了阻止两个线程对一个共享资源进行并发访问,因而推荐使用可能被并发访问的共享资源充当同步监视器

    public void run() {
            //使用account作为同步监视器,任何线程进入同步代码块之前必须获得对account的锁定,其他线程无法解锁,也无法修改它
            //加锁 --> 执行代码块 -->释放锁
            synchronized(account) {
                if(account.getBalance() >= drawMoney) {
                    System.out.println(getName() + "取钱成功!吐出钞票:" + drawMoney);
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    account.setBalance(account.getBalance() - drawMoney);
                    System.out.println("	余额为:" + account.getBalance());
                }else {
                    System.out.println(getName() + "取钱失败!余额不足");
                }
            }
        }

    温故而知新
  • 相关阅读:
    1.4(java学习笔记) 面向对象内存分析
    1.3(java学习笔记)构造方法及重载
    1.2(java学习笔记)类与对象
    1.1(java学习笔记) 面向过程与面向对象
    STM32F0库函数初始化系列:GPIO配置
    STM32F4库函数初始化系列:PWM输出
    STM32F4库函数初始化系列:DMA串口接收
    STM32F4库函数初始化系列:三重ADC——DMA
    STM32F1库函数初始化系列:DMA—ADC采集
    STM32F4库函数初始化系列:串口DMA接收
  • 原文地址:https://www.cnblogs.com/Uzai/p/9674728.html
Copyright © 2020-2023  润新知