首页 新闻 会员 周边

多线程并发安全问题

0
悬赏园豆:100 [已解决问题] 解决于 2018-12-07 11:13

此方法为什么会有并发问题?已加锁,依然会有并发覆盖,(出错位置为,多个线程操作同一Session)

(该方法功能为文件分片创建临时文件对象,并将文件对象保存到当前session中,以便于分片合并,问题出在当流程走chunks分支,操作session时会出现并发问题;当加锁时,应当会锁住当前对象;这个方法实现类取自springmvc容器,为单例对象,理论上同一时刻只会有一个线程才能取得这个锁,个人理解应当不会出现并发问题,不知道是不是哪个地方没有想到?希望高人指点

 

 

flag含义:chunks:为分片创建文件;single:为单文件(不需要切片)创建文件,merging:为合并分片创建文件;tempWorkPath:分片临时保存目录地址;saveFilePath:最终文件保存地址)

 

 

 

 

复制代码
@Override
    synchronized public File  GenerateDirPathForCurrFile(MutilFileInfo fileinfo,String flag) throws Exception {
        String fileName = fileinfo.getName();
        String lastModifiedDate = fileinfo.getLastModifiedDate();
        String fileSize = fileinfo.getSize();
        String type = fileinfo.getType();
        String id = fileinfo.getId();
        long timeStemp=System.currentTimeMillis();
        if("single".equals(flag)||"merging".equals(flag)) {
            String extName = fileName.substring(fileName.lastIndexOf("."));
            String fileNameSource = fileName+lastModifiedDate+fileSize+type+id+timeStemp;
            String fileDirName = SHA256Util.getSHA256StrJava(fileNameSource)+extName;
            File targetFile = new File(saveFilePath,fileDirName);
            while(targetFile.exists()){
                fileNameSource=fileNameSource+"1";
                fileDirName = SHA256Util.getSHA256StrJava(fileNameSource)+extName;
                targetFile = new File(fileDirName);
            }
            return targetFile;
        }else if("chunks".equals(flag)) {
            String fileNameSource = tempWorkPath+"/"+timeStemp+"_"+fileName+"_"+"part"+fileinfo.getChunk();
            File tempFile = new File(fileNameSource);
            fileinfo.setFileChunk(tempFile);
            if(SessionUtils.getSessionAttribute("fileChunks")==null){
                //fileChunksMapLock.lock();//此处加锁,防止并发创建时fileChunks中数据被覆盖
                    if(SessionUtils.getSessionAttribute("fileChunks")==null){
                        ConcurrentHashMap<String, Object> fileChunksMap = new ConcurrentHashMap<>();
                        SessionUtils.setSessionAttribute("fileChunks", fileChunksMap);
                        System.out.println("创建fileChunksMaps==========");
                    }
                //fileChunksMapLock.unlock();//释放锁
            }
            ConcurrentHashMap<String, Object> fileChunksMap = (ConcurrentHashMap<String, Object>) SessionUtils.getSessionAttribute("fileChunks");
            if(fileChunksMap.get(id+fileName)==null){
                //chunksArrLock.lock();//此处加锁,防止并发创建时chunksArr中数据被覆盖
                    if(fileChunksMap.get(id+fileName)==null){
                        //MutilFileInfo[] chunksArr = new MutilFileInfo[fileinfo.getChunks()];
                        List<MutilFileInfo> chunksArr=Collections.synchronizedList(new ArrayList<>());
                        fileChunksMap.put(id+fileName, chunksArr);
                        System.out.println("创建fileChunksArr==========");
                    }
                //chunksArrLock.unlock();//释放锁
            }
            @SuppressWarnings("unchecked")
            List<MutilFileInfo> chunksArr = (List<MutilFileInfo>) fileChunksMap.get(id+fileName);
            chunksArr.add(fileinfo);
            System.out.println("添加fileinfo:"+fileinfo);
            return tempFile;
        }else{
            throw new Exception("目标文件生成失败");
        }
    }
复制代码
夜半风起的主页 夜半风起 | 菜鸟二级 | 园豆:224
提问于:2018-12-06 10:37
< >
分享
最佳答案
0

问题现已解决,原因是前端jsessionId不一致造成的,前端并发提交时造成jsessionId覆盖,同时springboot2默认开启httpOnly也有点影响,后台线程同步那一块没有问题。

夜半风起 | 菜鸟二级 |园豆:224 | 2018-12-07 11:10
其他回答(2)
0

if(SessionUtils.getSessionAttribute("fileChunks")==null){
ConcurrentHashMap<String, Object> fileChunksMap = new ConcurrentHashMap<>();
SessionUtils.setSessionAttribute("fileChunks", fileChunksMap);
System.out.println("创建fileChunksMaps==========");
}
System.out.println("SessionUtils.getSessionAttribute-fileChunks" + SessionUtils.getSessionAttribute("fileChunks"));

你先下个main函数,测下如上代码,然后我看下结果;

收获园豆:100
奈何一笑 | 园豆:439 (菜鸟二级) | 2018-12-06 13:46

问题现已解决,原因是前端jsessionId不一致造成的,前端并发提交时造成jsessionId覆盖,同时springboot2默认开启httpOnly也有点影响,后台线程同步那一块没有问题。

支持(0) 反对(0) 夜半风起 | 园豆:224 (菜鸟二级) | 2018-12-07 11:09
0

首先确认下你这个从spring获取的对象真的是单例??按理说能并发说明拿到的锁不是同一个,你把代码修改为,锁代码块 ~加上 synchronized (this)试试~

队长给我球。 | 园豆:324 (菜鸟二级) | 2018-12-06 16:03

问题现已解决,原因是前端jsessionId不一致造成的,前端并发提交时造成jsessionId覆盖,同时springboot2默认开启httpOnly也有点影响,后台线程同步那一块没有问题。

支持(0) 反对(0) 夜半风起 | 园豆:224 (菜鸟二级) | 2018-12-07 11:09

对博客园的结帖机制有点懵逼,没有选择最佳答案,但园豆是默认给了第一楼,希望二楼的兄弟不要见怪哈!

支持(0) 反对(0) 夜半风起 | 园豆:224 (菜鸟二级) | 2018-12-07 11:18
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册