很小的一段多线程代码,如下:package untitled7;import java.io.*;
import java.nio.channels.*;public class Untitled2    extends Thread {
  private FileLock lock;  public void run() {
    try {
      FileOutputStream fout = new FileOutputStream("lock");
      lock = fout.getChannel().lock();
      System.out.println(hashCode() + " Locked");
      Thread.sleep(1000);
      System.out.println(hashCode() + " unLocked");
      lock.release();
      fout.close();
    }
    catch (Exception ex) {
      System.out.println("Lock Error: " + hashCode() + " " + ex.getMessage());
    }
  }
}----------------------------------------------------
调用部分为:
package untitled7;public class Untitled1 {
  public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
      Untitled2 untitled2 = new Untitled2();
      untitled2.start();
    }
  }
}理想产生的结果为:
[java@java java]$ java -jar test.jar
14285251 Locked
14285251 unLocked
10267414 Locked
10267414 unLocked
27553328 Locked
27553328 unLocked
11394033 Locked
11394033 unLocked
4384790 Locked
4384790 unLocked
9634993 Locked
9634993 unLocked
1641745 Locked
1641745 unLocked
11077203 Locked
11077203 unLocked
14576877 Locked
14576877 unLocked
12677476 Locked
12677476 unLocked但是在双至强的红旗Linux服务器(JDK1.5)下,却产生如下结果:
13446204 Locked
25615188 Locked
11107083 Locked
1267757 Locked
10584188 Locked
16416372 Locked
10584188 Locked
8568863 Locked
8451275 Locked
5737707 Locked
13446204 unLocked
1267757 unLocked
25615188 unLocked
11107083 unLocked
10584188 unLocked
8451275 unLocked
5737707 unLocked
16416372 unLocked
8568863 unLocked
10584188 unLocked
百思不得其解,特向兄弟们求助。

解决方案 »

  1.   

    FileLock是面向整个虚拟机的,而不是面向线程的,因此上面的结果是正确的,如果需要序列化线程对文件的加锁,可以引入一个锁对象,如下:
    package untitled7;import java.io.*;
    import java.nio.channels.*;public class Untitled2    extends Thread {
      private FileLock lock;  private static Object latch = new Object();  public void run() {
        synchronized(latch)
        {
          try {
            FileOutputStream fout = new FileOutputStream("lock");
            lock = fout.getChannel().lock();
            System.out.println(hashCode() + " Locked");
            Thread.sleep(1000);
            System.out.println(hashCode() + " unLocked");
            lock.release();
            fout.close();
          }
          catch (Exception ex) {
            System.out.println("Lock Error: " + hashCode() + " " + ex.getMessage());
          }
        };
      }
    }
      

  2.   

    先获取独占锁:
    RandomAccessFile raf = new RandomAccessFile( "usefilelocks.txt", "rw" );
    FileChannel fc = raf.getChannel();
    FileLock lock = fc.tryLock();
    然后建立共享内存
    MappedByteBuffer mapBuf = fc.map(FileChannel.MAP_RW,0,size);
    共享内存无论在JAVA还是在C/C++,它的特点就是:
    可以被多个进程打开访问;
    读写操作的进程在执行读写操作时其他进程不能进行写操作;也就是当前进程/线程在操作的时候,其它
    进程/线程是不可以读写的,虽然它打开了文件句柄.但不能同时读写.别外MappedByteBuffer虽然是JAVA对象,但实际操作的不是虚拟机上的内存,而是和C/C++一样直接操作的作业系统的文件内存映象.
      

  3.   

    哦,谢谢二位
    在filelock的jdk中确实找到如下字样。
    File locks are held on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads within the same virtual machine. 但是大多情况下,(俺的单CPU的redhat linux 9.0、Sco unix 5.0.5、Windows 2003、Windows xp、红旗4.0下都没有问题),只是在多cpu的红旗4.1下有问题,弄得我好郁闷。
    只好用别的办法曲折实现了,二位的办法都很不错。再次表示感谢
      

  4.   

    MappedByteBuffer不错,不过,程序和测试就要麻烦一些,而且,限制要更多一些。
      

  5.   

    单cpu实现线程是使用的时间片的轮转法,而多cpu可能一个cpu控制一个线程.
      

  6.   

    RandomAccessFile raf = new RandomAccessFile(new File("lock"), "rw");
        FileChannel fc = raf.getChannel();
        FileLock fl = fc.tryLock();
        if (fl.isValid()) {
          System.out.println(hashCode() + " Locked");
          Thread.sleep(1000);
          System.out.println(hashCode() + " unLocked");
          fl.release();
        }
        raf.close();
      

  7.   

    to laughsmile(海边的星空),谢谢,可您提供的这段代码在多线程多CPU的情况下也同样出现问题,先前我已经试验过了。
    to humanity(很健忘了) ,没错,排它锁确实需要写访问,如使用FileOutputStream和RandomAccessFile均可以。关键目前单独使用这种方式来进行同步看来是不成了,正在考虑其他办法中