- 同一个事情,老王和小张都以为还没处理,结果都去处理了,最后造成了成员工作量的浪费、甚至因为重复处理了一遍导致数据错误
- 两个有关联的事情分别给了老王和翠花,结果老王在等待翠花先给出结果再开始处理自己的事情,翠花也在等待老王先给出结果然后再处理自己的事情,结果两个人就这么一致等下去,事情一直没完成
- 同一个文档,小张和翠花各自更新的时候,出现相互覆盖的情况
- ...
一个运维管理系统,用于维护虚拟机资源以及部署的业务进程信息,且支持按照虚拟机维度和业务进程维度进行分别查看相关信息。即:假定基于SpringBoot框架进行代码实现,DeployedProcessService与VmService实例由Spring框架进行托管,为单例对象,然后彼此自动注入对方实例。假定由于业务逻辑需要,对两个服务类的执行方法进行了加锁处理。部署进程管理服务DEMO代码如下:
- 查看虚拟机VM信息,需要一并获取到上面部署的Process信息
- 查看Process信息,需要一并获取其所位于的虚拟机的信息。
不知道大家看到上面这个解释是啥感觉?懂还是不懂?反正我的经历是:在我懂之后,看这4点中的每一点都很在理;而我不懂时,我依旧不知道啥原因导致的死锁。其实,用白话解释死锁的产生原因,就是两个或者多个线程各自拿到了一个锁,然后自己依赖别人的锁,别人依赖自己的锁,然后彼此都在相互等待,永远没有办法等到。
- 互斥
- 占有并等待
- 非抢占
- 循环等待
一个好的经验,就是加锁的方法嵌套调用另一个加锁的方法时,多留个心眼,看看会不会出现相互依赖或者循环依赖的情况。锁优化思想——降低锁的影响
为了保证并发更新操作的准确性,对方法添加synchronized同步锁,保证多线程顺序执行:
- 校验当前用户是否有权更新
- 校验文章内容重复度
- 检查文章中是否有违禁词
- 更新到数据库中
- 加载到ES中
上面为啥要强调是JAVA7之前呢?因为JAVA7开始,ConcurrentHashMap的线程安全策略变了,改为了基于CAS的策略了。
比如下面图中的收费站场景,多条路最后需要经由同一个收费站,所以导致收费站这里会出现堵塞。而如果每条路都建一个自己的收费站,这样就有效避免了堵塞的状况。
一个SpringBoot构建的后端服务系统,对外以Controller方式提供诸多Restful接口方法供客户端调用。客户端调用的时候会携带token信息,然后鉴权逻辑中根据token获取到具体用户信息并缓存到内存中,后续的业务处理逻辑中有多处会需要获取该用户信息。这是ThreadLocal使用的一个典型场景,在通过token鉴权完成后,将用户信息设置到ThreadLocal对象中,这样后续所有需要用的地方,直接从ThreadLocal中获取就行了。
既然是为每个线程拷贝一份独立的副本,对于同一个线程而言拿到的数据是同一个,那么对于使用线程池来处理多任务的场景,线程都是重复利用的,这样会导致同一个线程中正在处理的任务可能会拿到上一个任务设置的共享值。对于业务处理而言可能会得到非预期结果。当然,除了可能会导致业务处理的时候前后任务缓存数据错乱,使用完毕不清理缓存,有些时候还容易导致内存泄漏的问题。所以编码的时候、尤其涉及内存资源使用的时候,用完回收始终会是一个好习惯。
有个需求任务跟踪管理系统,团队内的成员可以编辑团队内的待办需求事项的进展描述,如果团队内有两个人都打开了某一个需求页面进行编辑进展说明,那么第一个人改动完成存储的内容,会被第二个人保存改动时直接覆盖掉。
在单进程内的多线程间使用CAS机制保证并发的时候,需要结合volatile一起使用,以此来保证原子性与可见性。
数据库有一张“热议话题”表,表中每条记录有个“当前热度”字段,热度计算服务需要每隔5分钟执行一次计算,然后更新表中每条记录的热度字段。为了保证系统的高可用,热度计算服务部署了多个进程节点,由定时器触发,每隔5分钟计算一次。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) | Powered by Discuz! X3.4 |