概述
FileLock是java 1.4 版本后出現(xiàn)的一個(gè)類,它可以通過對一個(gè)可寫文件(w)加鎖赫模,保證同時(shí)只有一個(gè)進(jìn)程可以拿到文件的鎖树肃,這個(gè)進(jìn)程從而可以對文件做訪問;而其它拿不到鎖的進(jìn)程要么選擇被掛起等待瀑罗,要么選擇去做一些其它的事情胸嘴, 這樣的機(jī)制保證了眾進(jìn)程可以順序訪問該文件雏掠。也可以看出,能夠利用文件鎖的這種性質(zhì)劣像,在一些場景下乡话,雖然我們不需要操作某個(gè)文件, 但也可以通過 FileLock 來進(jìn)行并發(fā)控制驾讲,保證進(jìn)程的順序執(zhí)行蚊伞,避免數(shù)據(jù)錯(cuò)誤席赂。
共享鎖吮铭、獨(dú)占鎖
- 共享鎖:允許多個(gè)線程進(jìn)行文件的讀取操作
- 獨(dú)占鎖: 只允許一個(gè)線程進(jìn)行文件的讀/寫操作
獲得 FileLock
通過 NIO 的 API 首先獲取文件的 FileChannel ,然后可以通過 FileChannel 以下4中方式獲取FileLock颅停。
1. 通過lock() 獲取 FileLock谓晌,獲取文件的獨(dú)占鎖
public final FileLock lock() throws IOException {
return lock(0L, Long.MAX_VALUE, false);
}
默認(rèn)鎖定整個(gè)文件,并設(shè)置為獨(dú)占鎖癞揉。
2. 通過改方法可以鎖定文件的部分?jǐn)?shù)據(jù)纸肉,并支持設(shè)置共享鎖。
public FileLock lock(long position, long size, boolean shared) throws IOException{
......
}
- position:鎖定文件中的開始位置
- size: 鎖定文件中的內(nèi)容長度
- shared: 是否使用共享鎖喊熟。true為共享鎖定柏肪;false為獨(dú)占鎖定。
一些不支持共享鎖的操作系統(tǒng),將自動(dòng)將共享鎖改成排它鎖芥牌》澄叮可以通過調(diào)用isShared()方法來檢測獲得的是什么類型的鎖。
3. 試圖獲取文件獨(dú)占鎖
public final FileLock tryLock() throws IOException {
return tryLock(0L, Long.MAX_VALUE, false);
}
如果獲取不到鎖壁拉,則返回null谬俄。而不阻塞當(dāng)前線程,等待獲取鎖弃理。
4. 通過改方法可以嘗試獲得文件的部分?jǐn)?shù)據(jù)的鎖溃论,并支持設(shè)置共享鎖。
public abstract FileLock tryLock(long position, long size, boolean shared) throws IOException{
......
}
參數(shù)同上2痘昌。
如果獲取不到鎖钥勋,則返回null。
使用場景
- 如果多個(gè)應(yīng)用部署到同一臺機(jī)器上辆苔,并且同時(shí)操作同一份數(shù)據(jù)(數(shù)據(jù)庫中或文件中的數(shù)據(jù))算灸,可以使用FileLock充當(dāng)分布式鎖。
示例
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class FileLockTest {
public static void main(String[] args){
FileLock lock = null;
try (FileChannel channel = new FileOutputStream("d:\\file.lock",true).getChannel()){
lock = channel.lock();//無參lock()為獨(dú)占鎖
//lock = channel.lock(0L, channel.size(), true); //共享鎖
//其它邏輯
......
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (lock != null) {
try {
lock.release();
lock = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 對于一個(gè)只讀文件通過任意方式加鎖時(shí)會報(bào)NonWritableChannelException異常
- 無參lock()默認(rèn)為獨(dú)占鎖姑子,不會報(bào)NonReadableChannelException異常乎婿,因?yàn)楠?dú)占就是為了寫
- 有參lock()為共享鎖,所謂的共享也只能讀共享街佑,寫是獨(dú)占的谢翎,共享鎖控制的代碼只能是讀操作捍靠,當(dāng)有寫沖突時(shí)會報(bào)NonWritableChannelException異常
想了解更多精彩內(nèi)容請關(guān)注我的公眾號