换种角度理解Java中synchronized同步锁

Synchronized关键字用于处理线程安全问题

基本语法为:Synchronized(线程共享的对象){

                                   会出现线程安全问题的代码;

}

一个经典的线程安全问题:银行取款问题

//银行

class Bank{

    private int money = 1000;

   

    public int getMoney() {

        return money;

    }

    public void setMoney(int money) {

        this.money = money;

    }

}

//取钱的人

class Person extends Thread{

    public Bank money;

    public Person(Bank money){

        this.money = money;

    }

   

    public void run() {

                getMoney(1000);

    }

    public void getMoney(int num) {   

        if(money.getMoney() >= num) {

            money.setMoney(money.getMoney() - num);

            System.out.println("取了:" + num);

        }

    }

}

//执行代码

    public static void main(String[] args) {

        Bank money = new Bank();

        Person thread1 = new Person(money);

        Person thread2 = new Person(money);

        thread1.start();

        thread2.start();

    }

该代码的问题是:如果第一个线程A执行到if(money.getMoney() >= num)被另一个线程B抢走,那么当另一个线程B执行完之后,这个线程A会接着之前被中断的地方继续执行下去(保留现场,详细可翻阅操作系统书籍)。这时,由于线程不用继续判断if(money.getMoney() >= num)就可以继续执行下去,从而取款成功,所以就出现了线程安全问题。

这个时候,加上Synchronized关键字就可以完美解决:

    public void run() {

        synchronized (money) {

                getMoney(1000);

        }

    }

其实,这个被一些线程共享的对象可以被想象为一把钥匙,而这些线程有且只有这一把钥匙,当一个线程执行到Synchronized时,会先占有这把钥匙,直到整个Synchronized代码块结束,这个钥匙才被拿出来重新被这些线程争夺

posted @ 2020-11-25 19:55  TIME_小白  阅读(83)  评论(0)    收藏  举报