在 web 业务开发中究竟该如何使用锁?(中)

简介: 在 web 业务开发中究竟该如何使用锁?

2 锁和被保护的对象是不是同一层面

梳理要保护的对象是否是同一层面的。

案例

  • 累加counter
  • image.png测试
  • image.png
  • 因为传参运行100万次,所以执行后应该输出100万,但输出:
  • image.png
  • why?

在非静态的wrong方法上加锁,只能确保多线程无法执行同一实例的wrong,无法保证不执行不同实例的wrong。静态counter在多实例是共享的,所以会出现线程安全问题。

解决方案

在类中定义一个Object类型的静态字段,在操作counter之前对该字段加锁。

image.png

评论里肯定又有人会说:就这?直接把wrong定义为静态不就行?锁不就是类级别的了?

是可以,但不可能为解决线程安全改变代码结构,随便把实例方法改为静态方法。

3 加锁前考虑锁粒度和业务场景

方法上加synchronized加锁是简单,但也不能在业务代码中滥用:

  1. 没必要
    绝大多数业务代码是MVC三层架构,数据经过无状态的Controller=>Service=>Repository=>DB
    没必要使用synchronized保护什么数据。所以这也是为何很多同学笑评面试造火箭,工作拧螺丝~
  2. 大概率降低性能

使用Spring时,默认Controller、Service、Repository都是单例,加synchronized会导致整个程序几乎只能支持单线程,造成极大性能问题。

即使我们确实有一些共享资源需要保护,也要尽可能减小锁粒度。就像 concurrentHashMap 的一生发展。

案例

业务代码有个ArrayList会被多线程操作而需保护,但又有段比较耗时的不涉及线程安全的操作,应该如何加锁?

推荐只在操作ArrayList时给这ArrayList加锁。

1.png

正确加锁的版本几乎是对错误加锁的十倍性能。

细化锁后,性能还无法满足,就要考虑另一个维度的粒度问题:区分读写场景以及资源的访问冲突,考虑

4 悲观锁 V.S 乐观锁

一般业务代码很少需要进一步考虑这两种更细粒度的锁,自己结合业务的性能需求考虑是否要继续优化:

  1. 读写差异明显场景,考虑使用ReentrantReadWriteLock读写锁
  2. 若JDK版本>8、共享资源的冲突概率也没那么大,考虑使用StampedLock乐观读
  3. JDK的ReentrantLockReentrantReadWriteLock都提供了公平锁版本,在没有明确需求情况下不要轻易开启公平锁,在任务很轻情况下开启公平锁可能会让性能下降百倍

5 死锁

锁的粒度够用就好,这意味着程序逻辑中有时会存在一些细粒度锁。但一个业务逻辑如果涉及多锁,就很容易产生死锁。


案例

在电商场景的下单流程中,需要锁定订单中多个商品的库存,拿到所有商品的锁后再进行下单扣减库存,全部操作完成后释放所有锁。

上线后发现,下单失败概率高,失败后用户需重新下单,极大影响用户体验。

案发原因

因为扣减库存的顺序不同,导致并发下多个线程可能相互持有部分商品的锁,又等待其他线程释放另一部分商品的锁,于是出现死锁。

接下来,我们剖析一下核心的业务代码。

首先,定义一个商品类型,包含商品名、库存剩余和商品的库存锁三个属性,每一种商品默认库存1000个;然后,初始化10个这样的商品对象来模拟商品清单:

image.png

模拟在购物车进行商品选购,每次从商品清单(items字段)中随机选购三个商品(不考虑每次选购多个同类商品的逻辑,购物车中不体现商品数量):

image.png

目录
相关文章
|
22天前
|
监控 JavaScript 前端开发
《理解 WebSocket:Java Web 开发的实时通信技术》
【4月更文挑战第4天】WebSocket是Java Web实时通信的关键技术,提供双向持久连接,实现低延迟、高效率的实时交互。适用于聊天应用、在线游戏、数据监控和即时通知。开发涉及服务器端实现、客户端连接及数据协议定义,注意安全、错误处理、性能和兼容性。随着实时应用需求增加,WebSocket在Java Web开发中的地位将更加重要。
|
1月前
|
Web App开发 前端开发 开发工具
介绍Web开发的基础知识
介绍Web开发的基础知识
29 7
|
2天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
8天前
|
JSON Java fastjson
Spring Boot 底层级探索系列 04 - Web 开发(2)
Spring Boot 底层级探索系列 04 - Web 开发(2)
16 0
|
8天前
|
安全 编译器 PHP
PHP 8.1版本发布:引领Web开发新潮流
PHP编程语言一直是Web开发的主力军,而最新发布的PHP 8.1版本则为开发者们带来了更多创新和便利。本文将介绍PHP 8.1版本的主要特性,包括更快的性能、新的语言功能和增强的安全性,以及如何利用这些功能来提升Web应用程序的质量和效率。
|
11天前
|
PHP
web简易开发——通过php与HTML+css+mysql实现用户的登录,注册
web简易开发——通过php与HTML+css+mysql实现用户的登录,注册
|
11天前
|
前端开发 数据挖掘 API
使用Python中的Flask框架进行Web应用开发
【4月更文挑战第15天】在Python的Web开发领域,Flask是一个备受欢迎的轻量级Web框架。它简洁、灵活且易于扩展,使得开发者能够快速地构建出高质量的Web应用。本文将深入探讨Flask框架的核心特性、使用方法以及在实际开发中的应用。
|
20天前
|
安全 前端开发 Java
Java Web开发知识点学习总结
Java Web开发涉及Java基础、Servlet、JSP、数据库操作(SQL+JDBC)、MVC设计模式、Spring框架、Hibernate ORM、Web服务(SOAP&RESTful)、安全认证(HTTP Basic/Digest/OAuth)及性能优化(缓存、异步、负载均衡)。
18 3
|
23天前
|
XML JSON JavaScript
使用JSON和XML:数据交换格式在Java Web开发中的应用
【4月更文挑战第3天】本文比较了JSON和XML在Java Web开发中的应用。JSON是一种轻量级、易读的数据交换格式,适合快速解析和节省空间,常用于API和Web服务。XML则提供更强的灵活性和数据描述能力,适合复杂数据结构。Java有Jackson和Gson等库处理JSON,JAXB和DOM/SAX处理XML。选择格式需根据应用场景和需求。
|
27天前
|
前端开发 JavaScript 数据管理
描述一个使用Python开发Web应用程序的实际项目经验,包括所使用的框架和技术栈。
使用Flask开发Web应用,结合SQLite、Flask-SQLAlchemy进行数据管理,HTML/CSS/JS(Bootstrap和jQuery)构建前端。通过Flask路由处理用户请求,模块化代码提高可维护性。unittest进行测试,开发阶段用内置服务器,生产环境可选WSGI服务器或容器化部署。实现了用户注册登录和数据管理功能,展示Python Web开发的灵活性和效率。
15 4