2019-03-13 15:35
@goodsense 这个在框架层面是解决不了的,除非用 JDK 的 synchronized、lock 机制做一套 API 供大家在业务中使用,类似于一个多线程同步框架,这样来弄就与 JDK 提供的那套机制没多大差别了
注意一下,目前你的解决方案是不支持集群的,如果你用多个 JVM 跑你现在的同一个项目,即便用锁也是不行的,因为这个锁只是在同一个 JVM 中有效
使用我给的方案,由于是用的数据库事务机制,支持集群
2019-03-13 14:14
@416417521 打开浏览器开发者工具,看一下 js 不能用的原因,多数是 js 文件没被加载,很容解决
2019-03-13 13:47
1:假定有 A、B 两个并发线程
2:没加锁的那个版本,当 A 线程执行完下面代码得到 isSigned 后被操作系统挂起:
boolean isSigned = checkSignIn(userId, RuleID);
A 线程得到的 isSigned 是 false,并且在得到后立即被操作系统挂起
3:这时,线程 B 追上来,也执行到了 boolean isSigned = checkSignIn(userId, RuleID) 这行代码,也得到一个 false 值
4:接下来,A、B 继续向下执行,必然会引起重复签到和加分
这个问题显然是与 jfinal 无关的,是 java 的多线程基础问题。解决办法除了你的加锁版本以外,还可以通过数据库事务来解决,不要将 isSigned 读到内存中来,而是要让所有动作一气呵成,全部转化成数据库操作,大致如下:
Db.tx(() -> {
String sql = "(update user set score=score + 1 where id not in(select userId from user_signed where createDate = ?)";
int n1 = Db.update(sql, 今天日期);
// 插入一条签到数据
int n2 = Db.update("insert into user_signed ...");
return n1 > 0 && n2 > 0;
});
上面假定了你要更新的表是 user 的 score 字段,仅演示了加 1,假定签到表为 user_signed