如何理解和处理并发下的这些问题,你知道吗?

god_share 发布于 2015/03/13 14:36
阅读 871
收藏 1

简介:这几天看并发,看的越来越糊涂,并发中最容易出问题的就是锁。

语言:JAVA

问题描述:

   一、 在java 里,程序并发时,加锁,在文档,博客,书籍中,凡是说到并发,都会说一个东西,锁。java中使用最多的也就是内置锁,Java的关键字,synchronized,synchronized一般有两种方式,一种是方法锁,一种是代码块锁,现在不知道,这两种锁应用在什么地方?什么时候该用方法锁,什么时候用代码块锁?

    拿个例子来说:订单例子吧。

    要生成一个订单,首先订单号要唯一,订单号要唯一,肯定要加锁,一般估计生成订单号有一个单独的方法,锁应该是加载方法上。这时候订单号有了,当用户提交订单后,提交的方法里要执行下面几部操作。

    1.判断是否有库存,(这时候我不知道一般的商城是使用那种,查询锁定数据行,使用for update 给查询语句加锁有,根据返回数量判断,还是直接更新使用update 来扣减库存,如果更新返回是0,直接返回给用户,提示没有库存,直接结束,如果返回不为0,证明库存有,执行下面操作)

    2.生成唯一订单号。

    3.保存新增订单记录。

    4.保存新增订单明细。

    5.整个方法结束,返回提示给客户端,如果中途出错,直接事务回滚,返回订单提交失败。

这以上,是我自己猜测的一下操作流程,可能有很大问题,但是想问的是,并发情况下,处理订单提交的时候,如何加锁,不要出现死锁,保证数据一致性,并且性能也高?

    二、如何解决数据库的脏读,幻读,不可重复读等问题?

    不要说这些概念,这个概念性问题,我已经看了很多遍,主要是想问,在项目中,如果避免和解决这些问题的?

    不可重复读到还好处理一下,这个程序处理业务的时候注意一下,应该可以避免。

    但是脏读和幻读呢?该怎么解决?

    

加载中
0
熊大信了熊二的话
熊大信了熊二的话

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据

幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样

god_share
god_share
那个兄弟,这些概念我都知道,我是问怎么来处理,和避免发生这些情况?
0
i刘晓伟
i刘晓伟
同问。。做电商的 这个一直没彻底明白
0
零下三度
零下三度

需要加锁地方,我们一般会使用ReentrantLock,开销比synchronized小。

程序设计的方案有很多中,可以多线程并发处理,如果要线程之间做同步处理就蛋疼了,我所在的公司通常采用队列,将任务串行,省了很多事情。串行处理通常情况下,你说的脏读和幻读不存在了,如果真要并行程序,调试也是很难得事情,选择合适的语言工具如scala、erlang,了解一下这些为并发而生的语言机制,再来写会更好一点。

提高性能的可以考虑的方案很多,(1)可以将业务分片进行处理,(2)业务拆分为实时处理任务和异步处理任务,在接口调用的时候,将实时任务处理立即响应,将可以延时处理的异步执行,可以提高高并发的时候实时处理能力。(3)引入cache机制,cache分为local cache和全局cache,像生成流水好这种事情,采用cache来做,性能会更高一些吧,还要考虑集群生成的流水好必须唯一,使用Redis去做cache,Redis是单进程的,排队上厕所,你说的脏读和幻读不用担心了。

零下三度
零下三度
也是可以拆分的,生成流水号和业务数据检验是需要实时,但是业务数据入库可以异步执行。我觉得高并发下,用户是不应该直接触发数据库操作的,容易造成数据库卡顿,用户体验差。生成流水号可以通过cache和业务规则立即执行。
god_share
god_share
嗯,谢谢你的解答。 队列串行化,确实可以提高效率。将任务拆分成实时的不异步的,这种情况,一般是异步处理不需要返回值的时候,才可以,要不然还是拆分不了。像电商订单这种,没办法拆分吧。
返回顶部
顶部