Java并发编程2 —— synchronized关键字原理初探

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_25246305/article/details/82562325

线程安全问题的产生简单来说有两点,一是存在共享数据,二是存在多个线程同时操作共享数据。要解决这个问题,我们会想把处理共享数据的操作原子化,当一个线程在处理共享数据时,不允许其他线程同时处理它。换句话说,我们要把处理共享数据的这段逻辑“锁住”。

去银行

场景:俩人去银行,一个人存50块钱,另一个人取80块钱。银行一开始有一百块钱。

public class Bank {
    private static int total = 100;

    static class Service implements Runnable{
        private int money;
        private int operate;
        public Service(int money, int operate) {
            this.money = money;
            this.operate = operate;
        }

        @Override
        public void run() {
            total = operate == 0 ? total + money : total - money;
            System.out.println((operate == 0 ? "存入" : "取出") + money + "元,余额" + total + "元");
        }

    }

    public static void main(String[] args) {
        Service moneyIn = new Service(50, 0);
        Service moneyOut = new Service(80, 1);
        Thread inThread = new Thread(moneyIn);
        Thread outThread = new Thread(moneyOut);
        inThread.start();
        outThread.start();
    }
}

输出:

存入50元,余额70元
取出80元,余额70元

这个时候第一个人就懵逼了:我存的五十块钱哪去了?咋还倒少了三十???

实际上是在“存入50修改余额”到“打印存入50元,余额70元”这两个操作中间,第二个人已经完成了取钱的操作,余额已经变成了100+50-80=70。为了不让第一个人懵逼,我们应该把存钱取钱和打印余额的操作原子化,把这段逻辑锁住。

public class Bank {
    private static int total = 100;

    static class Service implements Runnable{
        private int money;
        private int operate;
        public Service(int money, int operate) {
            this.money = money;
            this.operate = operate;
        }

        @Override
        public synchronized void run() {
            total = operate == 0 ? total + money : total - money;
            System.out.println((operate == 0 ? "存入" : "取出") + money + "元,余额" + total + "元");
        }

    }

    public static void main(String[] args) {
        Service moneyIn = new Service(50, 0);
        Service moneyOut = new Service(80, 1);
        Thread inThread = new Thread(moneyIn);
        Thread outThread = new Thread(moneyOut);
        inThread.start();
        outThread.start();
    }
}

输出:

存入50元,余额150元
取出80元,余额70元

用synchronized把run方法锁住,同一时刻只有一个线程能进去操作total这个共享变量。

猜你喜欢

转载自blog.csdn.net/qq_25246305/article/details/82562325