java 文件鎖

JDK 1.4引入了文件加鎖機制,允許我們同步訪問一個共享文件,不過,競爭同一文件的兩個線程有可能在不同的java虛擬機上,或者一個是java線程,另一個是操作系統中其他的某個線程,但文件鎖對其他線程或其他操作系統進程都是可見的,因爲java的文件加鎖直接映射到了本地操作系統的加鎖機制。

注,這裏講的鎖是指鎖定其他應用程序,而不是鎖定同一虛擬機裏訪問的同一文件的其他線程 。如果在同一虛擬機兩次鎖定同一文件或某文件裏的同一區域,tryLock與lock則會拋出OverlappingFileLockException異常。

要想獲取整個文件的鎖,可以用FileChannel的tryLock( )或lock( )方法。(SocketChannel,DatagramChannel,以及 ServerSocketChannel是不需要鎖的,因爲它們是從單進程實體繼承而來;一般來說,你是不會讓兩個進程去共享一個網絡socket的。tryLock( ) 是非阻塞的,它會試着去獲取這個鎖,但是如果得不到(其它進程已經以獨佔方式得到這個鎖了),那它就直接返回;而lock( )是阻塞的,如果得不到鎖,它會在一直處於阻塞狀態,除非它得到了鎖,或者你打斷了調用它的線程,或者關閉了它要lock()的channel,否則它是不會返回的。最後用FileLock.release( )釋放鎖。
還可以像這樣鎖住文件的某一部分
tryLock(long position, long size, boolean shared) 
或者
lock(long position, long size, boolean shared) 
這個方法能鎖住文件的某個區域(size - position)。其中第三個參數表示是否是共享鎖。

雖然在修改文件的過程中,無參數的lock( )和tryLock( )方法的鎖定範圍會隨文件大小的變化,帶參數的方法卻不行。如果你鎖住了position到position+size這段範圍,而文件的長度又增加了,那麼position+size後面是不加鎖的。而無參數的lock方法則會鎖定整個文件,不管它變不變長。

鎖是獨佔的還是共享的,這要由操作系統來決定。如果操作系統不支持共享鎖,而程序又申請了一個共享鎖,那麼它會返回一個獨佔鎖。你可以用FileLock.isShared( )來查詢鎖的類型(共享還是獨佔)。

在寫文件時才能鎖定,如果對一個只讀文件通道進行鎖定操作時,會拋NonWritableChannelException異常,即new FileInputStream("data2.txt").getChannel().tryLock();時就會拋異常。

另外鎖定寫文件通道new FileOutputStream("data2.txt").getChannel().tryLock();時,它會清掉原文件中的內容,所以當文件中有內容時最好使用 new FileOutputStream("data2.txt",true).getChannel().tryLock(); 以追加方式打開寫文件通道。或者使用RandomAccessFile類來創建文件通道然後鎖定 new RandomAccessFile("data2.txt","rw").getChannel().tryLock(); ,這樣它不會破壞鎖定的文件的內容。

最後在使用tryLock()獲取鎖時, 有可能獲取不到,這時就會爲null,我們需能對此做相應處理

This file-locking API is intended to map directly to the native locking facility of the underlying operating system. Thus the locks held on a file should be visible to all programs that have access to the file, regardless of the language in which those programs are written.

This strongly suggests that its purpose is to be used between different processes.

This line:

They are not suitable for controlling access to a file by multiple threads within the same virtual machine.

suggests you should not use it if you have a single process with multiple threads. In that case you can instead use a synchronized section or a ReadWriteLock.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章