线程银行取钱例子

博客通过创建账户类和取钱线程,展示了在多线程环境下可能存在的问题,即并发取款导致资金不一致。为解决这个问题,文章探讨了Java中的线程锁,特别是`synchronized`关键字的使用,包括同步代码块、同步方法和Lock接口的锁机制,以确保线程安全地执行。
摘要由CSDN通过智能技术生成

创建账户类

public class Account {
    private String accountNum;
    private String pwd;
    private BigDecimal balance;

    public Account(){}

    public Account(String accountNum, String pwd, BigDecimal balance) {
        this.accountNum = accountNum;
        this.pwd = pwd;
        this.balance = balance;
    }

    public String getAccountNum() {
        return accountNum;
    }

    public void setAccountNum(String accountNum) {
        this.accountNum = accountNum;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public BigDecimal getBalance() {
        return balance;
    }

    public void setBalance(BigDecimal balance) {
        this.balance = balance;
    }
}

取钱线程

public class WithdrawTest {
    public static void main(String[] args) throws InterruptedException {
        Account account = new Account("123456","123456", new BigDecimal(3000));
        new WithdrawThread("A线程", account, new BigDecimal(800)).start();
        new WithdrawThread("B线程", account, new BigDecimal(800)).start();
    }
}

class WithdrawThread extends Thread{
    private Account account;
    private BigDecimal withdrawAmount;

    public WithdrawThread(String name, Account account, BigDecimal withdrawAmount){
        super(name);
        this.account = account;
        this.withdrawAmount = withdrawAmount;
    }

    @Override
    public void run(){
        if (account.getAccountNum().equals("123456") && account.getPwd().equals("123456")){
            // 判断账户余额大于等于取钱金额
            if (account.getBalance().compareTo(withdrawAmount) >=0){
                // 减去取的钱数
                account.setBalance(account.getBalance().subtract(withdrawAmount));
                System.out.println(getName() + "取钱成功,取出金额为:" + withdrawAmount);
                System.out.println("余额为:" + account.getBalance());
                return;
            }
            System.out.println(getName() + "取钱失败,余额为:" + account.getBalance());
            return;
        }
        System.out.println("账号或密码不正确");
    }
}

这样的线程会出现问题,两条线程交替运行,都可以取钱成功,但这样显然是不可以的。

所以就需要对线程进行操作,让它可以正确的运行。

线程锁

关键词:synchronized

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
  4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

方法一:同步代码块

@Override
    public void run(){
    	// 使用account作为同步监视器,任何线程进入下面同步代码块之前必须先获取对account的锁定,是的其他线程无法获取锁
        // 加锁 -> 处理业务逻辑(修改) -> 释放锁
        synchronized (account){
            if (account.getAccountNum().equals("123456") && account.getPwd().equals("123456")){
                // 判断账户余额大于等于取钱金额
                if (account.getBalance().compareTo(withdrawAmount) >=0){
                    // 减去
                    account.setBalance(account.getBalance().subtract(withdrawAmount));
                    System.out.println(getName() + "取钱成功,取出金额为:" + withdrawAmount);
                    System.out.println("余额为:" + account.getBalance());
                    return;
                }
                System.out.println(getName() + "取钱失败,余额为:" + account.getBalance());
                return;
            }
            System.out.println("账号或密码不正确");
        }
    }

方法二:同步方法

    public  void run(){
        withdraw(withdrawAmount);
    }

    public synchronized void withdraw(BigDecimal withdrawAmount){
        if (account.getAccountNum().equals("123456") && account.getPwd().equals("123456")){
            if (account.getBalance().compareTo(withdrawAmount) >=0){
                account.setBalance(account.getBalance().subtract(withdrawAmount));
                System.out.println(getName() + "取钱成功,取出金额为:" + withdrawAmount);
                System.out.println("余额为:" + account.getBalance());
                return;
            }
            System.out.println(getName() + "取钱失败,余额为:" + account.getBalance());
            return;
        }
        System.out.println("账号或密码不正确");
    }

方法三:同步锁lock

    public void run(){
        lock.lock();
        try {
            if (account.getAccountNum().equals("123456") && account.getPwd().equals("123456")){
            if (account.getBalance().compareTo(withdrawAmount) >=0){
                account.setBalance(account.getBalance().subtract(withdrawAmount));
                System.out.println(getName() + "取钱成功,取出金额为:" + withdrawAmount);
                System.out.println("余额为:" + account.getBalance());
                return;
            }
            System.out.println(getName() + "取钱失败,余额为:" + account.getBalance());
            return;
        }

        System.out.println("账号或密码不正确");
        }finally {
            lock.unlock();
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值