天天看點

NIO入門系列之第7章:檔案鎖定第7章 檔案鎖定

檔案鎖定初看起來可能讓人迷惑。它似乎指的是防止程式或者使用者通路特定檔案。事實上,檔案鎖就像正常的 Java 對象鎖—它們是勸告式的(advisory)鎖。它們不阻止任何形式的資料通路,相反,它們通過鎖的共享和擷取賴允許系統的不同部分互相協調。

您可以鎖定整個檔案或者檔案的一部分。如果您擷取一個排它鎖,那麼其他人就不能獲得同一個檔案或者檔案的一部分上的鎖。如果您獲得一個共享鎖,那麼其他人可以獲得同一個檔案或者檔案一部分上的共享鎖,但是不能獲得排它鎖。檔案鎖定并不總是出于保護資料的目的。例如,您可能臨時鎖定一個檔案以保證特定的寫操作成為原子的,而不會有其他程式的幹擾。

大多數作業系統提供了檔案系統鎖,但是它們并不都是采用同樣的方式。有些實作提供了共享鎖,而另一些僅提供了排它鎖。事實上,有些實作使得檔案的鎖定部分不可通路,盡管大多數實作不是這樣的。

在本節中,您将學習如何在NIO 中執行簡單的檔案鎖過程,我們還将探讨一些保證被鎖定的檔案盡可能可移植的方法。

要擷取檔案的一部分上的鎖,您要調用一個打開的 FileChannel 上的 lock() 方法。注意,如果要擷取一個排它鎖,您必須以寫方式打開檔案。

<code>RandomAccessFile raf = </code><code>new</code> <code>RandomAccessFile( </code><code>"usefilelocks.txt"</code><code>, </code><code>"rw"</code> <code>);</code>

<code>FileChannel fc = raf.getChannel();</code>

<code>FileLock lock = fc.lock( start, end, </code><code>false</code> <code>);</code>

在擁有鎖之後,您可以執行需要的任何敏感操作,然後再釋放鎖:

<code>lock.release();</code>

在釋放鎖後,嘗試獲得鎖的其他任何程式都有機會獲得它。

本小節的例子程式UseFileLocks.java 必須與它自己并行運作。這個程式擷取一個檔案上的鎖,持有三秒鐘,然後釋放它。如果同時運作這個程式的多個執行個體,您會看到每個執行個體依次獲得鎖。

<code>// UseFileLocks</code>

<code>import</code> <code>java.io.*;</code>

<code>import</code> <code>java.nio.*;</code>

<code>import</code> <code>java.nio.channels.*;</code>

<code>public</code> <code>class</code> <code>UseFileLocks</code>

<code>{</code>

<code>  </code><code>static</code> <code>private</code> <code>final</code> <code>int</code> <code>start = </code><code>10</code><code>;</code>

<code>  </code><code>static</code> <code>private</code> <code>final</code> <code>int</code> <code>end = </code><code>20</code><code>;</code>

<code>  </code><code>static</code> <code>public</code> <code>void</code> <code>main( String args[] ) </code><code>throws</code> <code>Exception {</code>

<code>    </code><code>// Get file channel</code>

<code>    </code><code>RandomAccessFile raf = </code><code>new</code> <code>RandomAccessFile( </code><code>"usefilelocks.txt"</code><code>, </code><code>"rw"</code> <code>);</code>

<code>    </code><code>FileChannel fc = raf.getChannel();</code>

<code>    </code><code>// Get lock</code>

<code>    </code><code>System.out.println( </code><code>"trying to get lock"</code> <code>);</code>

<code>    </code><code>FileLock lock = fc.lock( start, end, </code><code>false</code> <code>);</code>

<code>    </code><code>System.out.println( </code><code>"got lock!"</code> <code>);</code>

<code>    </code><code>// Pause</code>

<code>    </code><code>System.out.println( </code><code>"pausing"</code> <code>);</code>

<code>    </code><code>try</code> <code>{ Thread.sleep( </code><code>3000</code> <code>); } </code><code>catch</code><code>( InterruptedException ie ) {}</code>

<code>    </code><code>// Release lock</code>

<code>    </code><code>System.out.println( </code><code>"going to release lock"</code> <code>);</code>

<code>    </code><code>lock.release();</code>

<code>    </code><code>System.out.println( </code><code>"released lock"</code> <code>);</code>

<code>    </code><code>raf.close();</code>

<code>  </code><code>}</code>

<code>}</code>

檔案鎖定可能是一個複雜的操作,特别是考慮到不同的作業系統是以不同的方式實作鎖這一事實。下面的指導原則将幫助您盡可能保持代碼的可移植性:

隻使用排它鎖。

将所有的鎖視為勸告式的(advisory)

本文轉自 夢朝思夕 51CTO部落格,原文連結:http://blog.51cto.com/qiangmzsx/1410778

繼續閱讀