0

我有一个由多个线程访问的通用方法,

     public void m(String fileName)
     {         
       FileOutputStream fos= new FileOutputStream(fileName);
       FileChannel fc = fos.getChannel();
       fc.tryLock();
       ....

有时文件名在两个或多个线程中可能相同,当我使用 tryLock() 或 lock() 时出现异常。我如何知道是否已经获得了锁?

更新

import java.io.FileOutputStream;
import java.nio.channels.FileChannel;

class A implements Runnable{
    @Override
    public void run()
    {
        try
        {   
            FileOutputStream fos= new FileOutputStream("file.2txt");
            FileChannel fc = fos.getChannel();
            fc.tryLock();                                

            Thread.sleep(4000);

            fc.close();            
            System.out.println("done");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }        
    }
}

public class Test 
{
    public static void main(String[] args) throws Exception 
    {
        new Thread(new A()).start();
        Thread.sleep(2000);
        new Thread(new A()).start();  
    }
}

我得到一个例外:

java.nio.channels.OverlappingFileLockException
    at sun.nio.ch.FileChannelImpl$SharedFileLockTable.checkList(Unknown Source)
    at sun.nio.ch.FileChannelImpl$SharedFileLockTable.add(Unknown Source)
    at sun.nio.ch.FileChannelImpl.tryLock(Unknown Source)
    at java.nio.channels.FileChannel.tryLock(Unknown Source)
    at run.A.run(Test.java:14)
    at java.lang.Thread.run(Unknown Source)
4

2 回答 2

2

我如何知道是否已经获得了锁?

最好的答案是使用fc.tryLock();. 但是,它不应该抛出异常。null如果无法获取锁,它将返回。这是查看锁是否未锁定的最佳方法。

引用FileChannel.tryLock() 的 javadocs

此方法不会阻塞。调用总是立即返回,无论是在请求的区域上获得了锁还是没有这样做。如果由于另一个程序持有重叠锁而未能获取锁,则返回 null。如果由于任何其他原因未能获得锁,则会引发适当的异常。

于 2013-06-13T15:45:41.613 回答
1

正确的。所以它的行为符合预期,因为用户试图在一个程序中两次获取锁(如果另一个程序拥有锁,则返回 null,所有线程都在一个程序中)。我不愿意建议将捕获该异常作为判断锁是否已经到位的一种方式。听起来您最好在程序中设置另一个内部变量来保持锁定状态。或者捕获异常并用它来表示“在这个程序中已经获得了锁”。

于 2013-06-13T16:17:21.960 回答