`
Donald_Draper
  • 浏览: 984400 次
社区版块
存档分类
最新评论

文件通道解析二(文件锁,关闭通道)

    博客分类:
  • NIO
nio 
阅读更多
文件通道解析一(读写操作,通道数据传输等):http://donald-draper.iteye.com/blog/2374603
引言:
上一篇文章看了文件通道,读写操作,通道数据传输操作,先来回顾一下:
    文件通道的构造,主要是初始化通道读写模式,追加模式append及文件分发器,FileDispatcherImpl。
    文件通道的读写操作的实际操作都是由IOUtil协助FileDispatcherImpl完成,这一点和SocketChannel通道读写思路基本相同。
    文件通道传输方法transferTo,首先确保当前文件通道是否打开,是否可读,然后检查目的通道是否关闭,是否可写;然后先调用文件通道本地方法传输通道的数据到目的通道,如果失败,则将文件通道数据,映射到内存MappedByteBuffer,然后调用目的通道的写操作(MappedByteBuffer),如果再失败,则将通道数据,写到DirectByteBuffer中,然后在调用目的通道的写操作(DirectByteBuffer)。
     文件通道传输方法transferFrom,确保当前通道可写,打开,源通道可读打开,如果源通道为文件通道,将源通道数据映射的内存MappedByteBuffer,然后由IOUtil协助FileDispatcherImpl,将MappedByteBuffer
写入当前通道,如果源通道非文件通道,则先调用源通道的读操作,从源通道读取数据,写到临时DirectByteBuffer,委托write,写DirectByteBuffer到当前通道,即由IOUtil协助FileDispatcherImpl,将DirectByteBuffer写入当前通道。
在往下看之前我们先把文件通道的相关filed贴出,以便我们理解:
public class FileChannelImpl extends FileChannel
{
 private static final long allocationGranularity = initIDs();
    private final FileDispatcher nd;//文件分发器
    private final FileDescriptor fd;//文件描述
    private final boolean writable;//通道是否可写
    private final boolean readable;//通道是否可读
    private final boolean append;//通道写是否为追加模式
    private final Object parent;//创建通道的对象
    //下面这些属性,暂时不能确定是具体什么意思,只能先从字面上去理解,
    //这里我们先放在这里,后面用到在讲
    private final NativeThreadSet threads = new NativeThreadSet(2);
    private final Object positionLock = new Object();//文件读写是位置锁
    private static volatile boolean transferSupported = true;//是否支持通道传输
    private static volatile boolean pipeSupported = true;//是否支持管道
    private static volatile boolean fileSupported = true;//是否支持文件
    private static final long MAPPED_TRANSFER_SIZE = 8388608L;/
    private static final int TRANSFER_SIZE = 8192;
    private static final int MAP_RO = 0;
    private static final int MAP_RW = 1;
    private static final int MAP_PV = 2;
    private volatile FileLockTable fileLockTable;//存放文件锁的Table
    private static boolean isSharedFileLockTable;//文件锁table是否为共享
    private static volatile boolean propertyChecked;
    static final boolean $assertionsDisabled = !sun/nio/ch/FileChannelImpl.desiredAssertionStatus();

    static 
    {
        //加载nio,net资源库
        Util.load();
    }
     private static native long initIDs();
 }

现在我们来文件的lock和trylock方法
再来看锁文件region方法:
public FileLock lock(long l, long l1, boolean flag)
        throws IOException
    {
        FileLockImpl filelockimpl;
        FileLockTable filelocktable;
        boolean flag1;
        int i;
        ensureOpen();
        if(flag && !readable)//如果写模式,锁不能为共享模式
            throw new NonReadableChannelException();
        if(!flag && !writable)//如果为读模,则锁必须共享模式
            throw new NonWritableChannelException();
	//创建文件锁
        filelockimpl = new FileLockImpl(this, l, l1, flag);
	//获取文件通道的文件锁table
        filelocktable = fileLockTable();
	//将文件锁,加入通道文件锁table中
        filelocktable.add(filelockimpl);
        flag1 = false;
        i = -1;
        FileLock filelock;
        begin();
        ...
        int j;
       //不断的尝试加锁,直到成功
        do
	    //尝试锁文件region
            j = nd.lock(fd, true, l, l1, flag);
        while(j == 2 && isOpen());
        if(isOpen())
        {
            if(j == 1)
            {
                if(!$assertionsDisabled && !flag)
                    throw new AssertionError();
		//创建新的文件锁
                FileLockImpl filelockimpl1 = new FileLockImpl(this, l, l1, false);
		//替换filelocktable旧的文件锁
                filelocktable.replace(filelockimpl, filelockimpl1);
                filelockimpl = filelockimpl1;
            }
            flag1 = true;
        }
	如果锁文件region失败,则从filelocktable移除
        if(!flag1)
            filelocktable.remove(filelockimpl);
        threads.remove(i);
        try
        {
            end(flag1);
        }
        catch(ClosedByInterruptException closedbyinterruptexception)
        {
            throw new FileLockInterruptionException();
        }
        ...
        return filelockimpl;
    }
 

//尝试加锁
public FileLock tryLock(long l, long l1, boolean flag)
        throws IOException
    {
        FileLockImpl filelockimpl;
        FileLockTable filelocktable;
        int j;
        ensureOpen();
        if(flag && !readable)//如果写模式,锁不能为共享模式
            throw new NonReadableChannelException();
        if(!flag && !writable)//如果为读模,则锁必须共享模式
            throw new NonWritableChannelException();
	 //创建文件锁
        filelockimpl = new FileLockImpl(this, l, l1, flag);
        filelocktable = fileLockTable();//获取文件通道的文件锁table
        filelocktable.add(filelockimpl);//将文件锁,加入通道文件锁table中
        j = threads.add();
        int i;
        Object obj;
        try
        {
            ensureOpen();
	    //尝试锁文件region
            i = nd.lock(fd, false, l, l1, flag);
        }
        catch(IOException ioexception)
        {
            filelocktable.remove(filelockimpl);
            throw ioexception;
        }
        ...
	//创建新的文件锁
        obj = new FileLockImpl(this, l, l1, false);
	//替换filelocktable旧的文件锁
        filelocktable.replace(filelockimpl, ((FileLock) (obj)));
        filelockimpl1 = ((FileLockImpl) (obj));
        threads.remove(j);
        return filelockimpl1;
        ...
    }

从lock方法和try方法来看,首先检查共享模式参数shared与当前通道的读写模式是否匹配,然后根具postion,size和shared信息构造文件锁FileLockImpl,添加到通道文件锁表filelocktable中,再通过文件分发器FileDispatcherImpl锁文件region,如果成功,则创建新的文件锁替换旧的文件锁。如果lock失败,则从通道文件锁表filelocktable移除先前添加的文件锁。这里为什么要先创建文件锁添加到通道文件锁表filelocktable中,可能是为了先抢占通道文件锁表的位置,再去通FileDispatcherImpl锁文件region,成功则创建新的文件锁替换旧的文件锁。lock方法和trylock方法不同的是在FileDispatcherImpl锁文件region这个过程,lock为循环文件region,直到成功,而trylock方法,只锁一次,成功则则创建新的文件锁替换旧的文件锁,失败则从通道文件锁表filelocktable移除先前添加的文件锁,返回。

lock方法和trylock方法我们几点要关注:
1.
 //创建文件锁
filelockimpl = new FileLockImpl(this, l, l1, flag);

2.
filelocktable = fileLockTable();//获取文件通道的文件锁table

3.
j = nd.lock(fd, true, l, l1, flag);

下面分别来看这几点:
1.
 //创建文件锁
filelockimpl = new FileLockImpl(this, l, l1, flag);

//FileLockImpl
public class FileLockImpl extends FileLock
{
    private volatile boolean valid;//有效性标志
    static final boolean $assertionsDisabled = !sun/nio/ch/FileLockImpl.desiredAssertionStatus();
    //构造
    FileLockImpl(FileChannel filechannel, long l, long l1, boolean flag)
    {
        super(filechannel, l, l1, flag);
        valid = true;//初始化有效
    }

    FileLockImpl(AsynchronousFileChannel asynchronousfilechannel, long l, long l1, boolean flag)
    {
        super(asynchronousfilechannel, l, l1, flag);
        valid = true;
    }
    //判断文件锁是否有效
    public boolean isValid()
    {
        return valid;
    }
    //使文件锁无效
    void invalidate()
    {
        //如果断言开启,断言线程是否持有锁
        if(!$assertionsDisabled && !Thread.holdsLock(this))
        {
            throw new AssertionError();
        } else
        {
            valid = false;
            return;
        }
    }
    //释放文件锁
    public synchronized void release()
        throws IOException
    {
       //获取锁关联的通道
        Channel channel = acquiredBy();
        if(!channel.isOpen())//通道关闭
            throw new ClosedChannelException();
        if(valid)//在通道有效的情况下
        {
            if(channel instanceof FileChannelImpl)
	        //将实际工作委托相应的通道
                ((FileChannelImpl)channel).release(this);
            else
            if(channel instanceof AsynchronousFileChannelImpl)
                ((AsynchronousFileChannelImpl)channel).release(this);
            else
                throw new AssertionError();
            valid = false;
        }
    }
}

//FileLock
public abstract class FileLock implements AutoCloseable {
    private final Channel channel;//锁关联通道
    private final long position;//文件锁region的起始位置
    private final long size;//region大小
    private final boolean shared;//是否为共享模式
    //构造文件锁
    protected FileLock(FileChannel channel,
                       long position, long size, boolean shared)
    {
        if (position < 0)
            throw new IllegalArgumentException("Negative position");
        if (size < 0)
            throw new IllegalArgumentException("Negative size");
        if (position + size < 0)
            throw new IllegalArgumentException("Negative position + size");
        this.channel = channel;
        this.position = position;
        this.size = size;
        this.shared = shared;
    }
   /**
     * Returns the file channel upon whose file this lock was acquired.
     *返回用有本文件锁的通道
     *  This method has been superseded by the {@link #acquiredBy acquiredBy}
     * method.
     *
     * @return  The file channel, or {@code null} if the file lock was not
     *          acquired by a file channel.
     */
    public final FileChannel channel() {
        return (channel instanceof FileChannel) ? (FileChannel)channel : null;
    }
     /**
     * Returns the channel upon whose file this lock was acquired.
     *//获取锁关联通道
     * @return  The channel upon whose file this lock was acquired.
     *
     * @since 1.7
     */
    public Channel acquiredBy() {
        return channel;
    }
    /**
     * Returns the position within the file of the first byte of the locked
     * region.
     *获取锁文件region的起始position
     *  A locked region need not be contained within, or even overlap, the
     * actual underlying file, so the value returned by this method may exceed
     * the file's current size.  

     *
     * @return  The position
     */
    public final long position() {
        return position;
    }

    /**
     * Returns the size of the locked region in bytes.
     *获取锁文件region的size
     *  A locked region need not be contained within, or even overlap, the
     * actual underlying file, so the value returned by this method may exceed
     * the file's current size.  

     *
     * @return  The size of the locked region
     */
    public final long size() {
        return size;
    }

    /**
     * Tells whether this lock is shared.  
     *判断锁是否为共享模式
     * @return <tt>true</tt> if lock is shared,
     *         <tt>false</tt> if it is exclusive
     */
    public final boolean isShared() {
        return shared;
    }

    /**
     * Tells whether or not this lock overlaps the given lock range.  </p>
     *//判断加锁的文件region是否重叠
     * @return  <tt>true</tt> if, and only if, this lock and the given lock
     *          range overlap by at least one byte
     */
    public final boolean overlaps(long position, long size) {
        if (position + size <= this.position)
            return false;               // That is below this
        if (this.position + this.size <= position)
            return false;               // This is below that
        return true;
    }

    /**
     * Tells whether or not this lock is valid.
     *判断锁是否有效
     *  A lock object remains valid until it is released or the associated
     * file channel is closed, whichever comes first.  

     *
     * @return  <tt>true</tt> if, and only if, this lock is valid
     */
    public abstract boolean isValid();

    /**
     * Releases this lock.
     *
     *  If this lock object is valid then invoking this method releases the
     * lock and renders the object invalid.  If this lock object is invalid
     * then invoking this method has no effect.  

     *释放锁
     * @throws  ClosedChannelException
     *          If the channel that was used to acquire this lock
     *          is no longer open
     *
     * @throws  IOException
     *          If an I/O error occurs
     */
    public abstract void release() throws IOException;

    /**
     * This method invokes the {@link #release} method. It was added
     * to the class so that it could be used in conjunction with the
     * automatic resource management block construct.
     *关闭文件锁
     * @since 1.7
     */
    public final void close() throws IOException {
        release();
    }
}

2.
filelocktable = fileLockTable();//获取文件通道的文件锁table


//获取文件通道的文件锁table
private FileLockTable fileLockTable()
        throws IOException
    {
        if(fileLockTable != null)
            break MISSING_BLOCK_LABEL_96;
        FileChannelImpl filechannelimpl = this;
        JVM INSTR monitorenter ;
        int i;
        if(fileLockTable != null)
            break MISSING_BLOCK_LABEL_84;
        if(!isSharedFileLockTable())
            break MISSING_BLOCK_LABEL_73;
        i = threads.add();
        ensureOpen();
	//如果为共享模式
        fileLockTable = FileLockTable.newSharedFileLockTable(this, fd);
        threads.remove(i);
        break MISSING_BLOCK_LABEL_84;
        Exception exception;
        exception;
        threads.remove(i);
        throw exception;
	//否则
        fileLockTable = new SimpleFileLockTable();
        break MISSING_BLOCK_LABEL_96;
        Exception exception1;
        exception1;
        throw exception1;
        return fileLockTable;
    }

从上面可以看出如果为通道文件锁表为共享模式,则创建SharedFileLockTable,否则为
SimpleFileLockTable;
上述方法中break MISSING_BLOCK_LABEL_73类似的语句,这就由于反编译错误导致的,break语句有两种,一种为平时我们用的无label的break,即在for或while,switch语句中直接break;,break还有一种方式为break Label;即跳出循环到指定的Label:
实例:
testLable:
for (obj : list){
     if (flag) 
        break testLable;
}

由于反编译插件无法识别这样的语句,所以出现break MISSING_BLOCK_LABEL_73类似的语句。

Branching Statements-The break Statement:http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
Dealing with labels in decompiled code:http://stackoverflow.com/questions/6347930/dealing-with-labels-in-decompiled-code
我们先看一下FileLockTable的定义
abstract class FileLockTable
{
    protected FileLockTable()
    {
    }
    //创建共享文件锁表
    public static FileLockTable newSharedFileLockTable(Channel channel, FileDescriptor filedescriptor)
        throws IOException
    {
        return new SharedFileLockTable(channel, filedescriptor);
    }
    public abstract void add(FileLock filelock)//添加
        throws OverlappingFileLockException;
    public abstract void remove(FileLock filelock);//移除
    public abstract List removeAll();//移除所有
    public abstract void replace(FileLock filelock, FileLock filelock1);//替换
}

再来看SimpleFileLockTable
//FileChannelImpl-SimpleFileLockTable
private static class SimpleFileLockTable extends FileLockTable
    {
        private final List lockList = new ArrayList(2);//文件锁集合
        static final boolean $assertionsDisabled = !sun/nio/ch/FileChannelImpl.desiredAssertionStatus();
        public SimpleFileLockTable()
        {
        }
	//添加文件锁
	 public void add(FileLock filelock)
            throws OverlappingFileLockException
        {
            synchronized(lockList)
            {
                checkList(filelock.position(), filelock.size());
                lockList.add(filelock);
            }
        }
	//查看添加的文件锁,是否与文件锁集合中,已经加锁的文件region重叠
	private void checkList(long l, long l1)
            throws OverlappingFileLockException
        {
	   //如果断言开启,当前线程不只有文件锁集合,则抛出AssertionError
            if(!$assertionsDisabled && !Thread.holdsLock(lockList))
                throw new AssertionError();
            //遍历当前文件锁集合,查看添加的文件锁,是否与已经加锁的文件region重叠,
	    //重叠则抛出OverlappingFileLockException
            for(Iterator iterator = lockList.iterator(); iterator.hasNext();)
            {
                FileLock filelock = (FileLock)iterator.next();
                if(filelock.overlaps(l, l1))
                    throw new OverlappingFileLockException();
            }

        }
        //移除文件锁
        public void remove(FileLock filelock)
        {
            synchronized(lockList)
            {
                lockList.remove(filelock);
            }
        }
       //移除所有文件锁
        public List removeAll()
        {
            List list = lockList;
            JVM INSTR monitorenter ;
            ArrayList arraylist;
            arraylist = new ArrayList(lockList);
            lockList.clear();//直接clear文件锁集合
            return arraylist;
            Exception exception;
            exception;
            throw exception;
        }
       //替换文件锁,先移除filelock,后添加filelock1
        public void replace(FileLock filelock, FileLock filelock1)
        {
            synchronized(lockList)
            {
                lockList.remove(filelock);
                lockList.add(filelock1);
            }
        }
    }

再来看SharedFileLockTable
class SharedFileLockTable extends FileLockTable
{
    private static ConcurrentHashMap lockMap = new ConcurrentHashMap();//文件锁Map
    private static ReferenceQueue queue = new ReferenceQueue();
    private final Channel channel;//关联通道
    private final FileKey fileKey;//文件锁key
    static final boolean $assertionsDisabled = !sun/nio/ch/SharedFileLockTable.desiredAssertionStatus();
    //文件锁引用
    private static class FileLockReference extends WeakReference
    {

        FileKey fileKey()
        {
            return fileKey;
        }

        private FileKey fileKey;

        FileLockReference(FileLock filelock, ReferenceQueue referencequeue, FileKey filekey)
        {
            super(filelock, referencequeue);
            fileKey = filekey;
        }
    }

    //构造共享文件锁table
    SharedFileLockTable(Channel channel1, FileDescriptor filedescriptor)
        throws IOException
    {
        channel = channel1;
	//创建文件key
        fileKey = FileKey.create(filedescriptor);
    }
    //添加文件锁
    public void add(FileLock filelock)
        throws OverlappingFileLockException
    {
       //从文件锁Map获取,文件key对应的锁集合
        Object obj = (List)lockMap.get(fileKey);
_L3:
        List list;
label0:
        {
            if(obj != null)
                break MISSING_BLOCK_LABEL_95;
	    //文件锁集合为null,则创建共享锁集合
            obj = new ArrayList(2);
            synchronized(obj)
            {
	        //将文件key与文件锁集合放入Map中
                list = (List)lockMap.putIfAbsent(fileKey, obj);
                if(list != null)
                    break label0;
		//将文件锁索引添加到锁集合中
                ((List) (obj)).add(new FileLockReference(filelock, queue, fileKey));
            }
            break; /* Loop/switch isn't completed */
        }
        obj2;
        JVM INSTR monitorexit ;
          goto _L1
        exception;
        throw exception;
_L1:
        obj = list;
        List list1;
label1:
        {
            synchronized(obj)
            {
                list1 = (List)lockMap.get(fileKey);
                if(obj != list1)
                    break label1;
                checkList(((List) (obj)), filelock.position(), filelock.size());
                ((List) (obj)).add(new FileLockReference(filelock, queue, fileKey));
            }
            break; /* Loop/switch isn't completed */
        }
        obj = list1;
        obj1;
        JVM INSTR monitorexit ;
        if(true) goto _L3; else goto _L2
        exception1;
        throw exception1;
_L2:
        removeStaleEntries();
        return;
    }
    //如果文件key对应的,文件锁集合为空,则从map中移除文件key Entry
    private void removeKeyIfEmpty(FileKey filekey, List list)
    {
        if(!$assertionsDisabled && !Thread.holdsLock(list))
            throw new AssertionError();
        if(!$assertionsDisabled && lockMap.get(filekey) != list)
            throw new AssertionError();
        if(list.isEmpty())
            lockMap.remove(filekey);
    }
    //移除文件锁
    public void remove(FileLock filelock)
    {
        if(!$assertionsDisabled && filelock == null)
            throw new AssertionError();
	//从锁Map中获取文件key对应的集合 
        List list = (List)lockMap.get(fileKey);
        if(list == null)
            return;
        synchronized(list)
        {
            int i = 0;
            do
            {
                if(i >= list.size())
                    break;
		//获取文件锁引用
                FileLockReference filelockreference = (FileLockReference)list.get(i);
		//参文件锁引用获取文件锁
                FileLock filelock1 = (FileLock)filelockreference.get();
                if(filelock1 == filelock)
                {
                    if(!$assertionsDisabled && (filelock1 == null || filelock1.acquiredBy() != channel))
                        throw new AssertionError();
		    //找到,则清除引用,help GC
                    filelockreference.clear();
                    list.remove(i);//从文件锁集合中移除
                    break;
                }
                i++;
            } while(true);
        }
    }
    //移除所有文件锁
    public List removeAll()
    {
        ArrayList arraylist = new ArrayList();
	//获取文件key的文件锁集合
        List list = (List)lockMap.get(fileKey);
        if(list != null)
            synchronized(list)
            {
	        //遍历锁集合,将通读文件的文件锁添加到arraylist
                for(int i = 0; i < list.size();)
                {
                    FileLockReference filelockreference = (FileLockReference)list.get(i);
                    FileLock filelock = (FileLock)filelockreference.get();
                    if(filelock != null && filelock.acquiredBy() == channel)
                    {
                        filelockreference.clear();
                        list.remove(i);
                        arraylist.add(filelock);
                    } else
                    {
                        i++;
                    }
                }
                //移除文件key的锁集合
                removeKeyIfEmpty(fileKey, list);
            }
        return arraylist;
    }
    //替换文件锁
    public void replace(FileLock filelock, FileLock filelock1)
    {
        //获取文件锁集合
        List list = (List)lockMap.get(fileKey);
        if(!$assertionsDisabled && list == null)
            throw new AssertionError();
        synchronized(list)
        {
            int i = 0;
            do
            {
                if(i >= list.size())
                    break;
                FileLockReference filelockreference = (FileLockReference)list.get(i);
                FileLock filelock2 = (FileLock)filelockreference.get();
                if(filelock2 == filelock)
                {
		    //找到对应的文件锁,则清除引用,help gc
                    filelockreference.clear();
                    list.set(i, new FileLockReference(filelock1, queue, fileKey));//替换文件锁引用
                    break;
                }
                i++;
            } while(true);
        }
    }
   //检查文件key的锁集中的文件锁,锁住文件的region是否重叠
    private void checkList(List list, long l, long l1)
        throws OverlappingFileLockException
    {
        if(!$assertionsDisabled && !Thread.holdsLock(list))
            throw new AssertionError();
        for(Iterator iterator = list.iterator(); iterator.hasNext();)
        {
            FileLockReference filelockreference = (FileLockReference)iterator.next();
            FileLock filelock = (FileLock)filelockreference.get();
            if(filelock != null && filelock.overlaps(l, l1))
                throw new OverlappingFileLockException();
        }

    }
    //清空文件锁Map
    private void removeStaleEntries()
    {
        do
        {
            FileLockReference filelockreference;
	    //从引用队列中取出文件锁引用
            if((filelockreference = (FileLockReference)queue.poll()) == null)
                break;
            //从文件锁引用获取文件key
            FileKey filekey = filelockreference.fileKey();
	    //获取文件key对应的文件锁
            List list = (List)lockMap.get(filekey);
            if(list != null)
                synchronized(list)
                {
                    list.remove(filelockreference);
		    //移除文件key对应的文件锁集合
                    removeKeyIfEmpty(filekey, list);
                }
        } while(true);
    }
}

SharedFileLockTable用于存储文件共享锁,SimpleFileLockTable用于存储文件互质锁;
两者最大的不同是SimpleFileLockTable用list去管理文件锁,而SharedFileLockTable
用于ConcurrentHashMap管理文件锁。
3.
j = nd.lock(fd, true, l, l1, flag);

//FileDispatcherImpl
int lock(FileDescriptor filedescriptor, boolean flag, long l, long l1, boolean flag1)
        throws IOException
    {
        return lock0(filedescriptor, flag, l, l1, flag1);
    }
 static native int lock0(FileDescriptor filedescriptor, boolean flag, long l, long l1, boolean flag1)
        throws IOException;

来看释放文件锁
 void release(FileLockImpl filelockimpl)
        throws IOException
    {
        int i = threads.add();
        ensureOpen();
	//文件分发器先释放锁住的文件region
        nd.release(fd, filelockimpl.position(), filelockimpl.size());
        ...
        if(!$assertionsDisabled && fileLockTable == null)
        {
            throw new AssertionError();
        } else
        {
	    //从文件锁table中移除文件锁
            fileLockTable.remove(filelockimpl);
            return;
        }
    }

来看这一句:
//文件分发器先释放锁住的文件region
nd.release(fd, filelockimpl.position(), filelockimpl.size());

//FileDispatcherImpl
void release(FileDescriptor filedescriptor, long l, long l1)
        throws IOException
    {
        release0(filedescriptor, l, l1);
    }
  static native void release0(FileDescriptor filedescriptor, long l, long l1)
        throws IOException

//获取文件锁table共享模式
private static boolean isSharedFileLockTable()
    {
        if(!propertyChecked)
            synchronized(sun/nio/ch/FileChannelImpl)
            {
                if(!propertyChecked)
                {
                    String s = (String)AccessController.doPrivileged(new GetPropertyAction("sun.nio.ch.disableSystemWideOverlappingFileLockCheck"));
                    isSharedFileLockTable = s == null || s.equals("false");
                    propertyChecked = true;
                }
            }
        return isSharedFileLockTable;
    }

再来看关闭通道
protected void implCloseChannel()
        throws IOException
    {
        if(fileLockTable != null)
        {
	    //清空文件锁table
            for(Iterator iterator = fileLockTable.removeAll().iterator(); iterator.hasNext();)
            {
                FileLock filelock = (FileLock)iterator.next();
                synchronized(filelock)
                {
                    if(filelock.isValid())
                    {
		        //释放文件锁,锁住的文件region
                        nd.release(fd, filelock.position(), filelock.size());
                        ((FileLockImpl)filelock).invalidate();//使文件锁无效
                    }
                }
            }

        }
	//预先关闭文件描述
        nd.preClose(fd);
        threads.signalAndWait();
	//如果父对象不为null,则关闭父对象,否则关闭文件分发器
        if(parent != null)
            ((Closeable)parent).close();
        else
            nd.close(fd);
    }

//FileDispatcherImpl
void close(FileDescriptor filedescriptor)
        throws IOException
    {
        close0(filedescriptor);
    }
 static native void close0(FileDescriptor filedescriptor)
        throws IOException;

总结:
lock方法和try方法,首先检查共享模式参数shared与当前通道的读写模式是否匹配,然后根据具postion,size和shared信息构造文件锁FileLockImpl,添加到通道文件锁表filelocktable中,再通过文件分发器FileDispatcherImpl锁文件region,如果成功,则创建新的文件锁替换旧的文件锁。如果lock失败,则从通道文件锁表filelocktable移除先前添加的文件锁。这里为什么要先创建文件锁添加到通道文件锁表filelocktable中,可能是为了先抢占通道文件锁表的位置,再去通FileDispatcherImpl锁文件region,成功则创建新的文件锁替换旧的文件锁。lock方法和trylock方法不同的是在FileDispatcherImpl锁文件region这个过程,lock为循环文件region,直到成功,而trylock方法,只锁一次,成功则则创建新的文件锁替换旧的文件锁,失败则从通道文件锁表filelocktable移除先前添加的文件锁,返回。


附:
public class FileKey
{
    private static native void initIDs();
    private long dwVolumeSerialNumber;
    private long nFileIndexHigh;
    private long nFileIndexLow;

    static 
    {
        initIDs();
    }
    private FileKey()
    {
    }

    public static FileKey create(FileDescriptor filedescriptor)
    {
        FileKey filekey = new FileKey();
        try
        {
            filekey.init(filedescriptor);
        }
        catch(IOException ioexception)
        {
            throw new Error(ioexception);
        }
        return filekey;
    }
    private native void init(FileDescriptor filedescriptor)
        throws IOException;
    public int hashCode()
    {
        return (int)(dwVolumeSerialNumber ^ dwVolumeSerialNumber >>> 32) + (int)(nFileIndexHigh ^ nFileIndexHigh >>> 32) + (int)(nFileIndexLow ^ nFileIndexHigh >>> 32);
    }

    public boolean equals(Object obj)
    {
        if(obj == this)
            return true;
        if(!(obj instanceof FileKey))
            return false;
        FileKey filekey = (FileKey)obj;
        return dwVolumeSerialNumber == filekey.dwVolumeSerialNumber && nFileIndexHigh == filekey.nFileIndexHigh && nFileIndexLow == filekey.nFileIndexLow;
    }
}

0
1
分享到:
评论

相关推荐

    蓝牙BLE全面最详细解析以及BLE智能车锁开发实例

    它选择合适的射频通道进行通信,检测和解析空中数据包,控制数据的发送时机,确保数据的完整性和可靠性,处理ACK确认及重传机制,并管理链路状态。此外,LL层还支持多连接,例如Nordic的BLE协议栈可同时支持20个连接...

    Java程序员面试可能遭遇的个专业技术陷阱解析.pdf,这是一份不错的文件

    finally块保证了即使在异常情况下,某些代码也能被执行,如关闭文件流或网络连接。理解并合理使用Checked和Unchecked异常是关键。 4. **JVM调优** - 面试陷阱:面试官可能会要求解释JVM的内存模型,或者如何设置...

    C语言实现FTP服务器.zip

    在实现过程中,开发者可能会遇到诸如内存管理、网络异常、文件锁等问题,需要通过编写健壮的代码来解决。通过这个项目,你可以深入理解网络编程的基本原理,以及FTP协议的工作机制。 在压缩包中的"C语言实现FTP...

    关于使用感知技术尽早检测仅退出和共享通道的说明.rar

    还有日志分析工具,它们能够解析应用的日志文件,找出潜在的问题线索。 此外,还有一些专门针对并发和共享资源管理的工具,如Java的VisualVM、Python的Multiprocessing库的debug模式,以及各种分布式系统的监控框架...

    行业分类-设备装置-电动推闩式逃生锁.zip

    本压缩包文件“行业分类-设备装置-电动推闩式逃生锁.zip”包含了一份详细的技术资料——“电动推闩式逃生锁.pdf”,以下将对其中的知识点进行深入解析。 首先,电动推闩式逃生锁的核心功能是提供一种自动或手动开启...

    大量批处理实用程序例程

    关闭IDE通道检测.bat 列举进程.bat 判断光驱是否可用.bat 判断光驱里有无光盘.bat 判断分区格式.bat 刷新策略.bat 取得硬盘数.bat 右键添加bat.bat 右键添加打开MS-DOS.bat 弹出光驱.bat 改变我的文档路径.bat 显示...

    UNIX环境高级编程第二版

    - **文件打开与关闭**:open、close等函数的使用方法及其注意事项。 - **文件读写操作**:read、write函数的基本用法以及高级功能,如非阻塞I/O、异步I/O等。 #### 5. 网络编程 - **套接字编程基础**:介绍socket...

    jdk1.7.0_67

    - **多路复用Socket(NIO.2)**:Java 7扩展了非阻塞I/O,引入了新的File API,提供了异步文件操作,支持文件通道和文件锁,使得文件操作更加高效。 - **改进的字符串操作**:如`String`类新增了`join()`方法,用于...

    消防安全管理制度文件03982.doc

    以下是基于提供的文件内容,对消防安全管理制度的详细解析: 1. 消防安全教育、培训制度: - 定期举办消防知识宣传活动,通过宣传栏和知识竞赛提升员工的消防安全意识。 - 组织员工学习消防法规和规章制度,使...

    linux_programming_code

    `open()`, `close()`, `read()`, `write()`等函数用于文件的打开、关闭、读写。同时,还有`lseek()`用于设置文件指针位置,`chmod()`用于改变文件权限,`unlink()`用于删除文件。 4. **多线程编程**:Linux支持...

    linux命令返回值的含义解析

    11. OS error code 11: Resource temporarily unavailable - 资源暂时不可用,如网络连接超时或文件锁。 12. OS error code 12: Cannot allocate memory - 内存分配失败,系统内存不足。 13. OS error code 13: ...

    消防安全管理制度文件.docx

    - 营业或工作期间,安全出口不得上锁,疏散指示标志不得被遮挡或关闭。 4. 消防控制中心管理制度: - 消防控制中心的操作员应熟悉各种消防设施的性能,确保应急时能快速、有序地操作。 - 认真记录消防值班情况,...

    UNIX 系统错误码表 aix版

    - **含义**:使用的文件描述符无效或已关闭。 #### 48. ENOEXEC (8) - **错误描述**:执行格式错误。 - **含义**:加载或执行的文件格式不被系统识别或支持。 #### 49. E2BIG (7) - **错误描述**:参数列表过...

    常用批处理-很实用的东西,要了就拿去

    在给定的压缩包文件中,包含了一系列与系统维护和优化相关的批处理脚本,让我们逐一解析这些脚本可能涉及的知识点。 1. XP开机优化.bat:这个批处理文件可能是用于优化Windows XP系统的启动过程,包括禁用不必要的...

    700个批处理打包下载.rar

    关闭IDE通道检测.bat 分离路径和文件名.cmd 列举水产品最高&最低价记录.cmd 列举进程.bat 创建url格式的快捷方式.cmd 删除N天之前的文件.cmd 删除当前目录下及其子文件夹中所有的空文件夹.cmd 删除所有以数字命名的...

    java虚拟机规范 Java SE7

    11. **NIO.2**:Java SE7扩展了非阻塞I/O(NIO),提供了文件系统路径、异步I/O操作和文件通道等新功能,增强了I/O性能。 12. **动态语言支持**:JDK 7增加了对动态语言的支持,如JSR 292,使得JVM可以更好地运行如...

    uart.zip_lpc2368 uart

    LPC2368提供了多个UART通道,通过库函数可以方便地管理这些通道,如`uart_open()`和`uart_close()`分别用于打开和关闭指定的UART通道。同时,为了防止数据冲突,还需要正确使用互斥锁等同步机制。 总结起来,...

    C语言并行爬虫(epoll).zip

    - 文件操作:C语言提供了一系列的stdio函数,如fopen、fread、fwrite和fclose等,用于文件的打开、读取、写入和关闭。 2. **网络编程**: - 套接字(Sockets):是网络通信的基础,用于创建进程间的通信通道,...

Global site tag (gtag.js) - Google Analytics