|
|
@@ -7,6 +7,8 @@ import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import java.util.Optional;
|
|
|
+import java.util.concurrent.locks.Lock;
|
|
|
+import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
|
|
@Service
|
|
|
public class StatisticService {
|
|
|
@@ -17,6 +19,9 @@ public class StatisticService {
|
|
|
this.statisticRepository = statisticRepository;
|
|
|
}
|
|
|
|
|
|
+ // 可重入锁,用于保证并发更新作答统计时的正确性
|
|
|
+ private final Lock lock = new ReentrantLock();
|
|
|
+
|
|
|
/**
|
|
|
* 获取题目作答统计
|
|
|
*/
|
|
|
@@ -39,7 +44,8 @@ public class StatisticService {
|
|
|
if (frequency < correctFrequency) {
|
|
|
throw new MyServiceException("400", "frequency should be no less than to correctFrequency");
|
|
|
}
|
|
|
- // todo: 这里要加行锁
|
|
|
+ // 这里要加锁,因为先查询再更新的操作不是原子的
|
|
|
+ lock.lock();
|
|
|
Optional<Statistic> optional = statisticRepository.findById(questionId);
|
|
|
Statistic s;
|
|
|
if (optional.isPresent()) {
|
|
|
@@ -47,12 +53,10 @@ public class StatisticService {
|
|
|
s.setFrequency(s.getFrequency() + frequency);
|
|
|
s.setCorrectFrequency(s.getCorrectFrequency() + correctFrequency);
|
|
|
} else {
|
|
|
- s = new Statistic();
|
|
|
- s.setQuestionId(questionId);
|
|
|
- s.setFrequency(frequency);
|
|
|
- s.setCorrectFrequency(correctFrequency);
|
|
|
+ s = new Statistic(questionId, frequency, correctFrequency);
|
|
|
}
|
|
|
statisticRepository.save(s);
|
|
|
+ lock.unlock();
|
|
|
}
|
|
|
|
|
|
}
|