多线程的同步问题

看一个例子,背景是,银行卡里有1000块钱,在柜台取800块钱,在提款机取800块钱,理论上来说,这个是不允许的

看看实现代码


package test;

public class FetchMoney {

    public static void main(String[] args) {

        Bank bank = new Bank();

        MoneyThread thread1 = new MoneyThread(bank); // 柜台手续线程
        MoneyThread thread2 = new MoneyThread(bank); // 自助机手续线程

        thread1.start();
        thread2.start();
    }

}

class Bank {
    private int money = 1000;

    public int getMoney(int money) {

        if(money < 0) {
            return -1;
        }

        if(money > this.money) {
            return -2;
        }

        try {
            Thread.sleep(1000); // 取钱前的一些准备工作
        } catch (Exception e) {
            e.printStackTrace();
        }

        this.money -= money;
        return money;
    }
}

class MoneyThread extends Thread {

    private Bank bank;

    public MoneyThread(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        System.out.println(bank.getMoney(800));
    }
}


执行的结果是

800
800

Process finished with exit code 0

1000块钱的余额居然真的取出2次800块钱了

问题的根源在于,2个线程会同时访问一个实例的某个成员变量,2条线程判断条件时成员变量的值均可能是还没取钱时候的值

要解决这个问题,我们可以这么想,取钱的时候(即调getMoney方法的时候),只允许1条线程访问,就解决了

代码如下:


package test;

public class FetchMoney {

    public static void main(String[] args) {

        Bank bank = new Bank();

        MoneyThread thread1 = new MoneyThread(bank); // 柜台手续线程
        MoneyThread thread2 = new MoneyThread(bank); // 自助机手续线程

        thread1.start();
        thread2.start();


    }

}

class Bank {
    private int money = 1000;

    public synchronized int getMoney(int money) {

        if(money < 0) {
            return -1;
        }

        if(money > this.money) {
            return -2;
        }

        try {
            Thread.sleep(1000); // 取钱前的一些准备工作
        } catch (Exception e) {
            e.printStackTrace();
        }

        this.money -= money;
        return money;
    }

    public int getMoney2(int money) {

        synchronized(this) {
            if (money < 0) {
                return -1;
            }

            if (money > this.money) {
                return -2;
            }

            try {
                Thread.sleep(1000); // 取钱前的一些准备工作
            } catch (Exception e) {
                e.printStackTrace();
            }

            this.money -= money;
        }
        return money;
    }
}

class MoneyThread extends Thread {

    private Bank bank;

    public MoneyThread(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        System.out.println(bank.getMoney(800));
    }
}


调用getMoney或者getMoney2都可以


结果为:

800
-2

Process finished with exit code 0


猜你喜欢

转载自blog.csdn.net/mweibiao/article/details/80338240