我的这个加入组队帖子的方法如何改造成双重检查锁形式?

我的这个加入组队帖子的方法如何改造成双重检查锁形式?,第1张

我的这个加入组队帖子的方法如何改造成双重检查锁形式?,第2张

我学长要求我在学校的小程序里做一个组队的功能,学生发帖可以发起组队贴,这样可以找到同好 下面是我写的方法的代码,学长希望将 synchronized 代码块改成双重检查锁的形式,我看了我以前的笔记,发现双重检查锁一般是用于单例模式中的,而不知道怎么将这个类改成单例模式的样子,实在不会了来问问

@CrossOrigin
@RestController
@Slf4j
@RequestMapping("/planet")
public class TeamController implements Teamable {

    @Resource
    MongoTemplate mongoTemplate;

    @Autowired
    ZKCourseCalling courseCalling;

    private Runtime runtime;

    @Override
    @ApiOperation("加入组队的帖子")
    @PostMapping("/teamUpWith")
    public R teamUp(@RequestParam String planetId, @RequestParam("weChat") String weChat){
        String openId = UniversityInterceptor.getOpenId();
        R userInfo = courseCalling.getUserInfo(openId);
        Object data = userInfo.getData().get("userInfo");
        User user = JSON.parseObject(JSON.toJSONString(data), User.class);
//        user = new User();
//        user.setOpenid("test");
//        user.setAvatarUrl("test");
        Planet planet = mongoTemplate.findById(planetId, Planet.class);
        if(planet==null){
            return R.error().message("没有找到该帖子");
        }
        Group group = planet.getGroup();
        if(group.getInNum().equals(group.getTotalNum())){
            return R.error().message("组队人数已满");
        }
        synchronized (this){
            Member member = new Member();
            member.setOpenId(user.getOpenid());
            member.setAvatarUrl(user.getAvatarUrl());
            member.setWechat(weChat);
            List<Member> memberList = group.getMemberList();
            memberList.add(member);
            group.setMemberList(memberList);
            group.setInNum(group.getInNum()+1);
            mongoTemplate.updateFirst(Query.query(Criteria.where("_id").is(planetId)),Update.update("group",group), Planet.class);
        }
        return R.ok();
    }
}

Planet 是帖子对象,Group 是组队属性,member 是存储具体组队对象的属性,注释的三行代码是创建 User 对象用于测试的代码,可以无视,synchronized 代码块上做的事就是取得帖子对象并做判断,代码块中往帖子对象中的 Group 属性赋予对应值最后更新数据库,也就是正式的加入组队方法。 就这些了,在线等 dalao 救一救

----------------------- 以下是精选回复-----------------------

答:可能是让你在 synchronized 中再查一次判断一次组队人数满没满?就是只有锁住的代码块会改变数量,在当前线程拿到锁时,上一个拿到锁的线程已经将组队人数搞满的。你可以多同时请求一下加入组队,会看到数据库中组队字段的人数超出设置的限制了。
答:没用过 mongodb
mongodb 没有行锁之类的吗
为啥要代码锁 锁 this 不就是全局都限制了,然而 planetId 不同的时候并不需要锁
答:双重锁的话,本质是拿到锁后要操作的东西不一定是最新状态,所以要再临界区里再读取一次,获取操作对象最新的状态并再次校验

你这个例子里就是两个人同时拿到一个 group ,
a 上锁,加入,保存,解锁
然后 b 再上锁,但是 b 操作的 group 对象还是 a 保存前的那个 group ,并不知道 a 已经加入并保存了,
所以要再读取一次数据库拿到最新的 group 再进行操作
答:用 redis incr... +1 大于总人数,那么就放弃。
答:多个线程操作数据库的时候,组队人数可能会多出,应该是在 sync 里面再写个"组队人数已满"的判断吧
答:我理解的双重检验是在正逻辑里做容错,你用反逻辑直接返回的思路和这个模式是反的

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » 我的这个加入组队帖子的方法如何改造成双重检查锁形式?

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情