Java并发导致数据混淆求助:多线程读文件出现异常数据
线程文件读取数据串流异常排查求助
现有两个线程通过readFileByBuffer方法读取文本文件:线程A读取内容全为“a”的文件,线程B读取内容全为“b”的文件,但checkLine方法偶尔会检测到数据异常。打印数据后发现线程A读取到混合数据(如aaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)。该问题难以复现,且仅在将Linux内核从3.10升级到4.19后出现,尝试升级OpenJDK并未解决问题,恳请提供排查建议。
相关代码如下:
public boolean readFileByBuffer(String fileName){ public boolean run(String fileName) { try(BufferedReader br = NewIoUtils.newBufferedReader(new FileReader(fileName))){ String readLine ; while((readLine = br.readLine()) != null){ checkLine(readLine); } return true; }catch (FileNotFoundException e){ System.out.printf("can't found file , fileName :%s ,异常",fileName ); }catch(Exception e){ System.out.printf("Reading file exception :fileName : %s ,异常",fileName ); } return false; } public boolean checkLine(String line){ if(StringUtils.isBlank(line)) { log.error("The current line does not exist,projectCode:() ,batchId:()",projectCode,transBatchId); return false; } List<String> contents = CheckConfigUtils.getSplitLine(line); if (contents == null|| contents.size() < fieldCount) { log.error("Check that the number of fields is less than the configured number"); return false; } } }
排查建议
- 优先检查
NewIoUtils.newBufferedReader的实现:确认该工具类是否存在线程不安全设计,比如复用全局缓冲区、Reader实例,或未正确隔离不同线程的IO资源。若多个线程共享同一个BufferedReader的底层缓冲区,必然会导致数据串流。 - 验证文件完整性:读取前对目标文件计算哈希值(如MD5、SHA-1),确认线程A读取的文件确实全为“a”,排除文件被其他进程意外写入的可能。
- 测试替换JDK原生IO实现:暂时用JDK原生的
new BufferedReader(new FileReader(fileName))替换NewIoUtils的实现,若问题消失,说明自定义工具类存在适配问题。 - 增加线程级追踪日志:给每个线程添加唯一标识,读取文件时打印线程ID、文件名、读取行的内容及哈希值,一旦出现异常即可精准定位数据来源。
- 排查Linux内核IO相关配置:4.19内核在文件缓存、IO调度上有较多改动,可检查
vm.dirty_ratio、vm.dirty_background_ratio等内存缓存参数,或尝试挂载文件系统时添加noatime/nodiratime参数,排查缓存一致性问题。 - 检查文件描述符与锁机制:用
lsof命令在问题出现时查看文件的打开进程,确认是否有其他进程对文件加锁或共享文件句柄;同时检查系统的文件描述符限制是否足够。 - 调整JVM IO参数:尝试添加JVM参数禁用部分IO优化,比如
-Dsun.nio.disableSystemWideOverlappingFileLockCheck=false,或调整-Xmx/-Xms参数,排查是否是JVM内存管理与内核缓存交互导致的异常。
内容的提问来源于stack exchange,提问作者tom.chen
相关产品推荐
相关产品推荐

