Java并发编程(五):前文示例中加锁与不加锁的解释

大家好,我是欧阳方超,公众号同名。在这里插入图片描述

1 概述

在上一篇博文中,通过一个示例演示了多线程带来的性能提升,其中里面提到模拟订单验证无需加锁、模拟订单价格计算无需加锁、模拟发送确认邮件无需加锁、扣减库存需要加锁,本篇来解释一下。

2 解释

2.1 为什么扣减库存需要加锁

// 不加锁的错误版本
public boolean deduct(int amount) {
    if (stock >= amount) {  // 检查库存
        // 假设这时线程被中断,其他线程也执行到这里
        Thread.sleep(10);   // 模拟数据库操作延迟
        stock -= amount;    // 扣减库存
        return true;
    }
    return false;
}

考虑以下场景:

  • 当前库存stock=10
  • 订单1要购买7个商品
  • 订单2要购买5个商品

线程1执行到if (stock >= amount),发现10 >= 7,准备扣减
同时线程2也执行到if (stock >= amount),发现10 >= 5,也准备扣减
结果:

  • 线程1扣减7个,库存变为3
  • 线程2扣减5个,库存变为-2
    这就出现了超卖问题!
// 正确的加锁版本
public boolean deduct(int amount) {
    synchronized (lock) {  // 加锁确保原子性
        if (stock >= amount) {
            stock -= amount;
            return true;
        }
        return false;
    }
}

2.2 为什么订单验证无需加锁

private void validateOrder(Order order) {
    // 验证订单信息,比如:
    boolean isValidAddress = checkAddress(order.getAddress());
    boolean isValidPayment = checkPayment(order.getPaymentInfo());
    boolean isValidPhone = checkPhone(order.getPhoneNumber());
    
    // 这些操作都只是读取订单自身的信息
    // 不会修改任何共享数据
    // 每个线程处理的是不同的订单对象
}

原因:

  1. 只读取当前订单对象的信息,不修改共享数据
  2. 每个线程处理不同的订单对象,互不影响
  3. 即使多个线程同时验证不同的订单,也不会产生数据竞争

2.3 为什么价格计算无需加锁

private void calculatePrice(Order order) {
    // 假设这是一个复杂的价格计算过程
    double basePrice = order.getBasePrice();
    double discount = calculateDiscount(order);
    double tax = calculateTax(order);
    double shippingFee = calculateShipping(order);
    
    double finalPrice = basePrice * (1 - discount) * (1 + tax) + shippingFee;
    order.setFinalPrice(finalPrice);
}

原因:
1. 所有计算都基于订单自身的数据
2. 如果需要读取一些公共数据(如折扣规则),通常这些数据是不可变的
3. 计算结果只写入当前订单对象

2.4 为什么发送确认邮件无需加锁

private void sendConfirmationEmail(Order order) {
    // 发送邮件的代码
    String email = order.getCustomerEmail();
    String content = generateEmailContent(order);
    emailService.send(email, content);
}

原因:
1. 每个订单发送自己的邮件,互不影响
2. 邮件服务通常是线程安全的
3. 即使多个线程同时发送邮件,也不会产生数据竞争

介绍了,为什么模拟订单验证无需加锁、模拟订单价格计算无需加锁、模拟发送确认邮件无需加锁,而扣减库存需要加锁。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。我们下次见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值