zoukankan      html  css  js  c++  java
  • 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() + "取钱失败!余额不足");
                }
            }
        }

    温故而知新
  • 相关阅读:
    用Zend Studio12 导入在workspace中的项目
    PHP 统计中文字符串的长度
    jQuery判断checkbox是否选中的3种方法
    js,jquery获取下拉框选中的option
    HTML与XHTML的区别
    HTML头部
    HTML框架标签
    js的继承
    图片懒加载
    Http请求的gzip压缩
  • 原文地址:https://www.cnblogs.com/Uzai/p/9674728.html
Copyright © 2011-2022 走看看