當前位置:
首頁 > 知識 > 文件通道解析二(文件鎖,關閉通道)

文件通道解析二(文件鎖,關閉通道)

文件通道解析一(讀寫操作,通道數據傳輸等):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);

下面分別來看這幾點:

//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 true if lock is shared,
* false if it is exclusive
*/
public final boolean isShared {
return shared;
}

/**
* Tells whether or not this lock overlaps the given lock range.

*//判斷加鎖的文件region是否重疊
* @return true 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 true 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;
}
}

//獲取文件通道的文件鎖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類似的語句。

我們先看一下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管理文件鎖。

//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;
}
}

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

linux c++爬蟲(一)
Azure Event Hub 技術研究系列2-發送事件到Event Hub
光速 React
Ubuntu14.04安裝samba
STM 8s 外部中斷寄存器無法寫入

TAG:科技優家 |

您可能感興趣

您知道網路文件系統嗎?
根文件系統詳解
中國文聯嚴正聲明:從未發布所謂名譽顧問申請備案文件
非人類級別的《GTA5》,解鎖文件「解救布萊恩」六星通緝!
漫談文件系統
安倍就森友文件改寫問題道歉 稱將推進事件調查
綠色通道關閉,遊戲業重歸起點:新監管文件制定中
一文看懂中央一號文件
驗證文件關於文檔的要求
英媒:秘密文件披露英國軍情六處曾暗助卡扎菲
軟網推薦:告別混亂 文件管理有條不紊
《請出示文件》證件類型一覽
node刪除當前文件夾下的所有文件和文件夾(不包括當前文件夾)
外國人在日本:日式文件五大不通情理之處
《真三國無雙8》更新移除所有中文字幕文件
《國家車聯網產業標準體系建設指南》系列文件解讀
特朗普將解密通俄調查文件 民主黨斥:對抗專案組調查
網傳文化和旅遊部「三定文件」披露
辦公室白領必會知識:Excel文件文件夾相關函數
《星神鏈》公布文件體積與遊戲封面等細節