簡體   English   中英

java內存映射文件多線程讀/寫

[英]java Memory mapped Files multithreading read / write

我有2個線程同時訪問同一個大文件(.txt)。

第一個線程正在從文件中讀取。 第二個線程正在寫入文件。

兩個線程都訪問相同的塊,例如(start:0,blocksize:10),但具有不同的通道和緩沖區實例

讀者:

{
     int BLOCK_SIZE = 10;
     byte[] bytesArr = new byte[BLOCK_SIZE];
     File file = new File("/db.txt");
     RandomAccessFile randomFile = new RandomAccessFile(file, "r");
     FileChannel channel = randomFile.getChannel();
     MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, BLOCK_SIZE);
     map.get(bytesArr , 0, BLOCK_SIZE);
     channel.close();
}

作家:

{
     int BLOCK_SIZE = 10;
     File file = new File("/db.txt");
     RandomAccessFile randomFile = new RandomAccessFile(file, "rw");
     FileChannel channel = randomFile.getChannel();
     MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, BLOCK_SIZE);
     map.put(bytesToWrite);
     channel.close();
}

我知道如果兩者同時開始,我將獲得重疊異常! 但是我想知道的是,在什么時候重疊正好是什么? 我的意思是什么時候發生“鎖定”? 示例:假設編寫者首先獲取訪問權限,然后如果讀者嘗試訪問,那么可能的情況是?:

 FileChannel channel = randomFile.getChannel();
 // 1- can reader access here?
 MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, BLOCK_SIZE);
 // 2- can reader access here?
 map.put(bytesToWrite);
 // 3- can reader access here?
 channel.close();
 // 4- can reader access here?

1,2,3或4?

沒有4肯定,因為頻道已關閉! 其他幾點呢?

謝謝!

我在與OP的聊天對話中總結了一些筆記。 OP具有心理模型(就像我們大多數人一樣),一旦線程寫入數據結構,該數據結構立即對所有其他線程可見。 在使用內存映射文件的OPs測試中,他已經確認在單個插槽Intel CPU上這似乎是正確的。

不幸的是,這不是真的,並且Java可以並確實顯示硬件的基本行為。 Java被設計為假設代碼是單線程的,因此可以這樣優化,直到它被告知為止。 這意味着硬件和熱點版本(以及熱點收集的統計信息)會有所不同。 這種復雜性,並在單個插槽上運行Intel CPU使OPs測試無效。

有關詳細信息,以下鏈接將有助於深入了解“Java內存模型”。 尤其是同步並不僅僅意味着“相互排斥”; 在硬件方面,它還涉及“數據可見性”和“指令排序”。 單線程代碼認為理所當然的兩個主題。

不要擔心,如果這需要時間沉入,並且你一開始感到不知所措。 起初我們都覺得這樣。 當且僅當你遵循這個簡單的規則時,Java才能隱藏這種復雜性。 當線程讀取或修改共享數據結構時,它必須位於同步塊內。 也就是說,寫作線程和閱讀線程。 顯然我正在簡化,但遵循該規則,程序將始終有效。 只有當你對Java內存模型,內存障礙以及它與不同硬件的關系有很深的理解時才打破它(即使然后並發專家甚至可以避免違反規則;單線程通常要簡單得多,可以令人驚訝地快速 ..許多低延遲系統設計為大多數單線程因此)。


直接回答OP問題。 問題中的示例代碼沒有鎖定。 沒有內存障礙,根本沒有並發控制。 因此,讀取和寫入將如何交互的行為是不確定的。 他們可能會工作,但他們可能不會。 他們大部分時間都可以工作。 英特爾擁有所有CPU的最強內存保證,並且在單個插槽上運行測試用例英特爾CPU將錯過許多復雜的錯誤。 在Java 5和JSR 133問世之前,Sun也被這個問題所困擾(閱讀有關為什么Double Checked Locking在Java中被破壞的文章更多細節)。

您不會從此代碼或任何塊中獲得任何鎖定異常。 文件鎖在進程之間而不是在線程之間運行。 你需要的是同步,信號量或ReadWriteLocks。 並且不需要使用兩個通道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM