客户端同时访问一个service,查询数据库状态,引发的不一致问题

terry21 2018-03-01 05:21:28

我的项目有一个场景:

客户端同时访问一个url,controller调用了service类,service类是一个spring单例bean,service持有一个mybatis的repository对象,查询了记录数,例如:select count(1) from table_test where name=?
然后做类似以下的判断:
if (count == 0) {
insert1();
} else {
insert2();
}
问题在,每个线程访问到的count居然都是一样的,

这样的场景,假如不使用对service的方法使用synchronized限定,要如何控制好一致性啊?
...全文
679 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
terry21 2018-03-05
  • 打赏
  • 举报
回复
引用 6 楼 lmx125254 的回复:
感觉你说的就是抢红包问题吧。放入2个队列就好。一个是1,剩下的放其他的就好了。访问1的就返回1,访问另一个队列的返回2.然后数据库根据缓存的东西再操作就OK了
目前的情况是: 例如,初始状态表无记录,5个请求同时请求,他们都查询到记录数为0,全部请求结束后,表有5条记录。 我希望的结果是: 例如,初始状态表无记录,5个请求同时请求,第1个请求查询到记录数为0,插一条记录,其余的请求可以马上知道表里已经有1条记录,全部请求结束后,表有5条记录。
Leonis丶L 2018-03-05
  • 打赏
  • 举报
回复
感觉你说的就是抢红包问题吧。放入2个队列就好。一个是1,剩下的放其他的就好了。访问1的就返回1,访问另一个队列的返回2.然后数据库根据缓存的东西再操作就OK了
terry21 2018-03-05
  • 打赏
  • 举报
回复
引用 4 楼 cgd125633600 的回复:
数据库里有插入东西吗
例如,初始状态表无记录,5个请求同时请求,他们都查询到记录数为0,全部请求结束后,表有5条记录。
且听师说 2018-03-05
  • 打赏
  • 举报
回复
csdn这个排版我也是醉了、、、
且听师说 2018-03-05
  • 打赏
  • 举报
回复
我的思路是这样的: 首先从你的描述看你的插入语句只分两种情况 ,1不存在符合的数据 2存在符合的数据 在dao层上增加一个 currenthashmap,以name为key 通过维护这个字段,保证数据的插入语句正确 这个方案有个问题是可能会出现过大的hashmap内存溢出,可以通过使用缓存解决,思路都是一样的 public class MockDBTest { private HashMap<String,Integer> names = new HashMap<>(); int selectName(String name){ Integer count = names.get(name); if(count == null){ synchronized (this){ count = names.get(name); if(count == null){ names.put(name,1); return 0; } } } return count; } void insert1(){ System.out.println("插入语句1"); } void insert2(){ System.out.println("插入语句2"); } public static void main(String[] args) { MockDBTest db = new MockDBTest(); for (int i = 0; i <20 ; i++) { Thread thread = new Thread(()->{ Integer count = db.selectName("test1"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if(count == 0){ db.insert1(); }else{ db.insert2(); } }); thread.start(); } } }
Leonis丶L 2018-03-05
  • 打赏
  • 举报
回复
引用 7 楼 terry21 的回复:
[quote=引用 6 楼 lmx125254 的回复:] 感觉你说的就是抢红包问题吧。放入2个队列就好。一个是1,剩下的放其他的就好了。访问1的就返回1,访问另一个队列的返回2.然后数据库根据缓存的东西再操作就OK了
目前的情况是: 例如,初始状态表无记录,5个请求同时请求,他们都查询到记录数为0,全部请求结束后,表有5条记录。 我希望的结果是: 例如,初始状态表无记录,5个请求同时请求,第1个请求查询到记录数为0,插一条记录,其余的请求可以马上知道表里已经有1条记录,全部请求结束后,表有5条记录。[/quote] 是的。我说的就是这种。你可以百度下抢红包的实现方式
mml_慢慢来 2018-03-02
  • 打赏
  • 举报
回复
单例跟线程安全没关系
maradona1984 2018-03-02
  • 打赏
  • 举报
回复
按你描述的场景,是不需要进行任何控制的,查询本就不涉及到数据不一致的问题 每次返回同样的数据,我觉得你应该检查代码是不是写的有问题
HumbertC 2018-03-02
  • 打赏
  • 举报
回复
数据库里有插入东西吗
terry21 2018-03-02
  • 打赏
  • 举报
回复
多个请求同一时刻都去查数据库记录数,同时查到记录数为0,然后都执行了insert1(); 我想要的结果正常的情况应该是:第一个请求执行insert1(); 接下来的其他请求都执行insert2(); 有没有什么串行化的办法?

81,091

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧