文件锁的使用及真正的并发

      这次测试的情况比较特殊。测试一张订单拆成2张,其中一张模拟成功的结果,一张模拟失败的结果。我模拟的服务端通过“读取文件内容,然后修改内容,再返回原内容”模式将原内容返回的同时又能保证下一次读取的文件内容和上一次的不同,但是测试的客户端代码采用并发发送请求的模式,导致我模拟的服务端返回的文件内容有时候出现相同的内容。这是因为第一个线程读取完文件内容并且还没有完成修改保存,第二个线程就将文件内容读取了。所以需要使用文件锁。

    我百度了文件锁的使用,http://www.cnblogs.com/yejg1212/archive/2013/03/31/2991963.html此网址的博客说

RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel fc = raf.getChannel();
FileLock fl = fc.tryLock();
通过这段代码把文件锁住,但是对方在接下来的文件操作里,读取和写入文件使用的不是raf这个流,而是自行new了fileReader和filewriter流。我试了下,完全不行,提示文件已经被其他线程锁住了。
而我换成raf来读文件,成功读取了文件内容。读文件还是使用readLine方法,写的话使用writeBytes(String s)。试过用writechars(String s),结果文件内容是每个字符后接1个null,读出来的内容是每个字符后都跟1个空格。

实践发现,如果单次单次的调用程序,能够成功,凡是并发调用,写入文件就有问题了。后来我在readFile和changeFIle方法里都加了写入文件的方法,用的是filewriter流,结果filwriter流写入的文件是正常的。我想我大概找到问题的症结了,因为filewriter有flush方法,而randomaccessfile没有flush方法,所以并发的时候第二次读文件的时候,randomaccessfile流里还有缓存没有清掉,而我手动两次运行的时候,因为有间隔,缓存已经清掉了,从而没有出现问题,这种可读可写的流就是不好用。按照猜想,我试着在要操作的文件里只放入1k大小的内容,运行后发现randomaccessfile流写入没有问题了。然后找到解决办法了,我在目标文件里不存请求内容了,我存请求内容的文件名。将要用到的几种请求内容分别放到不同文件里,然后目标文件放第一个请求内容的文件名,然后修改目标文件里请求内容的文件名,由于请求内容的文件没有被锁,所以可以用filereader读
另:经过三天的查资料然后调试,最后还是修改模拟器的代码,将模拟器相关servlet的service方法设成synchronized的,其余内容不变,这样的话,就能从源头上将并发请求变成串行的。
另:如果是采用
Thread t1=new Thread(tr); t1.start();Thread t2=new Thread(tr);t2.start();来测试我的模拟脚本,发现用了文件锁后能正常运行。但是new出两个线程然后放到线程池运行就可能会有问题了。然后看了下Thread的start方法,居然是synchronized并且如果threadStatus不为0就throw new IllegalThreadStateException(),里面还调用native(调用非java code就用这个) void start0()方法。




posted on 2016-06-06 16:33  在天成象  阅读(436)  评论(0)    收藏  举报