现实际业务中会出现这样的一种情况
id name total
1 zhangsan 5
表数据为此,在正常情况下我们对这笔记录去处理update的操作
首先肯定是查出来这笔记录
然后再进行update操作 对total ++ 或 -- 操作;
但是如果并发情况下会出现这样的情况
我两条线程同时进入
然后同时查出来数据total都是5
然后第一条线程要对这个total + 5 那么total结果应该是10
由于是并发同时进入另一条线程查出来 这个total也应该是与第一条线程修改之前一样 total = 5
但是第二条线程要对total值进行 -3 的操作 那么total = 5 - 3 = 2
然后不管两条线程谁先谁后最后这个total值可能是 2 或者 10 都不是我们想要的正确值
实际上我们想要的值应该是 5 - 3 + 5 = 7 (正确值)
这时候数据库里面就存在了脏数据
锁机制可以解决这种问题
第一种:悲观锁(synchronized关键字)
synchronized可以修饰实例方法,静态方法,代码块。
如果在上面的方法上加上这个关键字那么就可以解决这种问题
但是synchronized关键字他是去锁住线程进入当前有且仅有一条线程可以进入
例如你去上厕所 厕所外面有一个大门你把大门给锁上了,里面其实有很多厕所可以使用你仅仅使用了一个
这样做就导致了系统处理性能变慢,不符合高并发高性能的理念
说他是悲观锁其实意思就是:我知道这个方法肯定会出错,那么我就把这个方法锁上
第二种:乐观锁
这种机制仅仅只需要在数据库上加上一个字段version
id name total version
1 zhangsan 5 1
我每次去对这笔记录去进行update的操作就把version+1 并且你的update语句要带上version参数
这意思就是两条线程同时进入
第一条线程进入查询出来id = 1, total = 5, version = 1 我进行update操作对totalNew = total + 5 ,versionNew = version + 1
update table_name
set total = totalNew , version = versionNew
where id = id and version = version
记录就变成了
id name total version
1 zhangsan 10 2
第二条线程进入由于是和第一条同时进入那么查询出来其实和第一条线程一样 total = 5 version = 1
我进行update操作对totalNew = total - 2 ,versionNew = version + 1
update table_name
set total = totalNew , version = versionNew
where id = id and version = version
这时候线程二找不到这个version = 1 id = 1 的记录那么update的记录就为0
代码中接收到update返回为0 那么就可以进行操作失败的业务处理,至于重新执行或者返回提示就看业务了
这样做相对于悲观锁我既能够保证并发并且不会出现数据问题
并且现在好像有个什么规定尽量避免或者不使用悲观锁,毕竟悲观锁影响了系统的性能操作