FileLock,文件鎖。
文件鎖在OS中很常見,如果多個程序同時訪問、修改同一個文件,很容易因為文件數據不同步而出現問題。給文件加一個鎖,同一時間,只能有一個程序修改此文件,或者程序都只能讀此文件,這就解決了同步問題,保證了線程安全。
文件鎖是進程級別的,不是線程級別的。文件鎖可以解決多個進程並發訪問、修改同一個文件的問題,但不能解決多線程並發訪問、修改同一文件的問題。
就是說使用文件鎖時,同一進程內(同一個程序中)的多個線程,可以同時訪問、修改此文件。
文件鎖是當前程序所屬的JVM實例持有的,一旦獲取到文件鎖(對文件加鎖),要調用release(),或者關閉對應的FileChannel對象,或者當前JVM退出,才會釋放這個鎖。
一旦某個進程(比如說JVM實例)對某個文件加鎖,則在釋放這個鎖之前,此進程不能再對此文件加鎖,就是說JVM實例在同一文件上的文件鎖是不重疊的(進程級別不能重復在同一文件上獲取鎖)。
文件鎖分為2類:
- 排它鎖:又叫獨占鎖。對文件加排它鎖后,該進程可以對此文件進行讀寫,該進程獨占此文件,其他進程不能讀寫此文件,直到該進程釋放文件鎖。
- 共享鎖:某個進程對文件加共享鎖,其他進程也可以訪問此文件,但這些進程都只能讀此文件,不能寫。線程是安全的。只要還有一個進程持有共享鎖,此文件就只能讀,不能寫。
使用示例:
1 //創建FileChannel對象,文件鎖只能通過FileChannel對象來使用 2 FileChannel fileChannel=new FileOutputStream("./1.txt").getChannel(); 3 4 //對文件加鎖 5 FileLock lock=fileChannel.lock(); 6 7 //對此文件進行一些讀寫操作。 8 //....... 9 10 //釋放鎖 11 lock.release();
文件鎖要通過FileChannel對象使用。
有4種獲取文件鎖的方法:
- lock() //對整個文件加鎖,默認為排它鎖。
- lock(long position, long size, booean shared) //自定義加鎖方式。前2個參數指定要加鎖的部分(可以只對此文件的部分內容加鎖),第三個參數值指定是否是共享鎖。
- tryLock() //對整個文件加鎖,默認為排它鎖。
- tryLock(long position, long size, booean shared) //自定義加鎖方式。
如果指定為共享鎖,則其它進程可讀此文件,所有進程均不能寫此文件,如果某進程試圖對此文件進行寫操作,會拋出異常。
lock與tryLock的區別:
- lock是阻塞式的,如果未獲取到文件鎖,會一直阻塞當前線程,直到獲取文件鎖
- tryLock和lock的作用相同,只不過tryLock是非阻塞式的,tryLock是嘗試獲取文件鎖,獲取成功就返回鎖對象,否則返回null,不會阻塞當前線程。
FileLock常用的2個方法:
boolean isShared() //此文件鎖是否是共享鎖
boolean isValid() //此文件鎖是否還有效
在某些OS上,對某個文件加鎖后,不能對此文件使用通道映射。
如何避免死鎖:在讀寫關鍵數據時加鎖,操作完成后解鎖;一次性申請所有需要的資源,並且在申請不成功的情況下放棄已申請到的資源。