Java多线程/并发05、synchronized应用实例:线程间操作共享数据

电商平台中最重要的一点就是卖东西。同个商品不能无限制的卖下去的,因为商品有库存量,超过库存就不能卖了。
这里,约定一个规则,下单使库存减n,取消订单使库存加m。库存数量不可以小于0。
假设平台上同时有很多用户在操作,在不考虑效率的情况下,我们用同步方法来模拟这个场景。

首先写一个订单处理类:

class OrderHandler{
    /*初始某商品库存量*/
    int StockSomeGoodsNum=200;
    /*用户下单*/
    public void Produce(int n){
        /*step1:判断可用库存操作*/
        if((StockSomeGoodsNum-n)>=0){
            /*为了更好体现线程间的竞争,让进程休眠一下*/
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            /*step2:执行减少库存操作*/
            StockSomeGoodsNum-=n;
            System.out.println("用户" + Thread.currentThread().getName()
                    + "成功购买商品:" + String.valueOf(n)+"个,库存剩余"+StockSomeGoodsNum+"个");
        }else{
            System.out.println("用户" + Thread.currentThread().getName()
                    + "下单失败,库存不足" + String.valueOf(n)+"个,库存剩余"+StockSomeGoodsNum+"个");
        }
    }
  /*用户取消订单*/
    public void Cancel(int n){
        StockSomeGoodsNum+=n;
        System.out.println("用户" + Thread.currentThread().getName()
                + "取消购买商品:" + String.valueOf(n)+"个,库存剩余"+StockSomeGoodsNum+"个");
    }

}

可以看到类中的两个方法都会操作StockSomeGoodsNum变量
在用户下单方法void Produce(int n)中,首先判断库存数量够不够,如果够了对库存数量进行减少操作。这里涉及两个步骤:判断库存、减少库存。这两个步骤组成一个事务,是不允许分开和打乱的。但现在是多个线程并发执行,就有可能在这两个步骤之间,有别的线程执行了增减库存操作。

现在在主函数中开启多个线程来模拟用户下单和取消订单的操作:

public static void main(String[] args) {
        final OrderHandler orderHandler=new OrderHandler();
        /*开启10个线程,模拟10个用户进行下单操作*/
        for(int i=0;i<10;i++){
            new Thread(new Runnable() {
                public void run() {
                    /*每个人购买商品数量为25个*/
                    orderHandler.Produce(25);
                }
            }).start();
        }
        /*开启5个线程,模拟5个用户在进行取消订单操作*/
        for(int i=0;i<5;i++){
            new Thread(new Runnable() {
                public void run() {
                    /*每个取消订单中包含的商品数为3个*/
                    orderHandler.Cancel(3);
                }
            }).start();
        }
    }
}

运行结果:

用户Thread-10取消购买商品:3个,库存剩余203个
用户Thread-12取消购买商品:3个,库存剩余209个
用户Thread-11取消购买商品:3个,库存剩余206个
用户Thread-13取消购买商品:3个,库存剩余212个
用户Thread-14取消购买商品:3个,库存剩余215个
用户Thread-1成功购买商品:25个,库存剩余165个
用户Thread-2成功购买商品:25个,库存剩余140个
用户Thread-0成功购买商品:25个,库存剩余165个
用户Thread-3成功购买商品:25个,库存剩余115个
用户Thread-4成功购买商品:25个,库存剩余65个
用户Thread-5成功购买商品:25个,库存剩余65个
用户Thread-8成功购买商品:25个,库存剩余-10个
用户Thread-6成功购买商品:25个,库存剩余15个
用户Thread-7成功购买商品:25个,库存剩余-10个
用户Thread-9成功购买商品:25个,库存剩余-35

出现了负数,说明在判断库存、减少库存的两个步骤中有其它线程执行,导致结果不正确。现在我们在Produce()和Cancle()方法前加上synchronized关键字,让它们成为同步方法。
再次运行结果:

用户Thread-0成功购买商品:25个,库存剩余175个
用户Thread-14取消购买商品:3个,库存剩余178个
用户Thread-13取消购买商品:3个,库存剩余181个
用户Thread-12取消购买商品:3个,库存剩余184个
用户Thread-11取消购买商品:3个,库存剩余187个
用户Thread-10取消购买商品:3个,库存剩余190个
用户Thread-9成功购买商品:25个,库存剩余165个
用户Thread-8成功购买商品:25个,库存剩余140个
用户Thread-7成功购买商品:25个,库存剩余115个
用户Thread-6成功购买商品:25个,库存剩余90个
用户Thread-5成功购买商品:25个,库存剩余65个
用户Thread-4成功购买商品:25个,库存剩余40个
用户Thread-3成功购买商品:25个,库存剩余15个
用户Thread-2下单失败,库存不足25个,库存剩余15个
用户Thread-1下单失败,库存不足25个,库存剩余15个

结论:

各个线程间能保持如此好的协作,其关键原因就是OrderHandler类中的方法都是synchronized同步方法,因此他们有共同的锁:this,当一个线程运行时,其它线程都被阻塞,这样保证了程序的正常运行。
synchronized同步方法虽然很安全,但效率也很低。synchronized同步方法是串行运行的,多个线程排队,并没有并发执行。因此在实际业务开发中要注意。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值