threadsafe_Agrona的Threadsafe堆缓冲区
threadsafe
這篇博客文章通過說明我們如何輕松訪問線程內存來進行線程安全操作,繼續了我在Agrona庫上進行的系列文章 。 在繼續討論這是一個相當高級的主題之前,我可能應該警告一下,并且我不嘗試解釋諸如內存屏障之類的概念,僅概述API的功能。
ByteBuffer的不足
Java提供了一個字節緩沖區類來包裝offheap和onheap內存。 字節緩沖區在Java網絡堆棧中專門用作從中讀取或寫入數據的位置。
那么字節緩沖區有什么問題呢? 好吧,因為它們針對用例,所以它們不提供對原子操作之類的支持。 如果要編寫可從不同進程同時訪問的非堆數據結構,則字節緩沖區無法滿足您的需求。 您可能要編寫的那種庫的一個示例是一個消息隊列,一個進程將讀取該消息,而另一個進程將寫入該消息隊列。
Agrona的緩沖器
Agrona提供了幾種緩沖區類和接口來克服這些缺陷。 Aeron和SBE庫都使用這些緩沖區。
拆分緩沖區而不是分配單個類的決定是出于希望限制不同系統組件對緩沖區的訪問權限的考慮。 如果一個類只需要從一個緩沖區中讀取,則不應允許它通過使緩沖區發生突變而將錯誤引入系統。 同樣,不允許設計為單線程的組件使用Atomic操作。
包裝一些內存
為了能夠使用緩沖區執行任何操作,您需要告訴它緩沖區的起始位置! 此過程稱為包裝基礎內存。 所有包裝內存的方法都稱為wrap并且可以包裝byte[] , ByteBuffer或DirectBuffer 。 您還可以指定用于包裝數據結構的偏移量和長度。 例如,這里是包裝byte[] 。
final int offset = 0;final int length = 5;buffer.wrap(new byte[length], offset, length);包裝還有另一個選擇–這是存儲位置的地址。 在這種情況下,該方法采用存儲器的基地址及其長度。 這是為了支持諸如通過sun.misc.Unsafe分配的內存或例如malloc調用之類的事情。 這是使用Unsafe的示例。
final int length = 10;final long address = unsafe.allocateMemory(length);buffer.wrap(address, length);包裝內存還可以設置緩沖區的容量,可以通過capacity()方法進行訪問。
存取器
因此,現在您有了可以讀取和寫入的堆外內存緩沖區。 約定是,每個getter以單詞get開頭,并以您要獲取的值的類型作為后綴。 您需要提供一個地址,以說出要讀取的緩沖區中的位置。 還有一個可選的字節順序參數。 如果未指定字節順序,則將使用計算機的本機順序。 這是一個有關如何在緩沖區開始處加長的示例:
final int address = 0;long value = buffer.getLong(address, ByteOrder.BIG_ENDIAN);value++;buffer.putLong(address, value, ByteOrder.BIG_ENDIAN);除基本類型外,還可以從緩沖區中獲取和放入字節。 在這種情況下,要讀取或讀取的緩沖區作為參數傳遞。 再次支持byte[] , ByteBuffer或DirectBuffer 。 例如,這是將數據讀入byte[] 。
final int offsetInBuffer = 0;final int offsetInResult = 0;final int length = 5;final byte[] result = new byte[length];buffer.getBytes(offsetInBuffer, result, offsetInResult, length, result);并發操作
int和long值也可以使用內存排序語義進行讀取或寫入。 后綴為Ordered方法保證它們最終將被設置為所討論的值,并且該值最終將在另一個對該值進行易失性讀取的線程中可見。 換句話說, putLongOrdered自動執行存儲存儲內存屏障 。 get*Volatile和put*Volatile遵循與在Java中用volatile關鍵字聲明的變量的讀寫相同的排序語義。
也可以通過AtomicBuffer更復雜的內存操作。 例如,有一個compareAndSetLong ,它將在給定的索引上原子地設置一個更新的值,給定的現有值是一個期望值。 getAndAddLong方法是在給定索引處添加的完全原子的方法。
生活中沒有什么是免費的,所有這些都需要警告。 如果您的索引詞不對齊,這些保證將不存在。 請記住,它也有可能撕裂一些薄弱內存體系結構,如ARM和Sparc過字邊界寫入值,看到堆棧溢出對這種事情的更多細節。
邊界檢查
邊界檢查是棘手的問題之一,也是正在進行的辯論的主題。 避免邊界檢查可以提高代碼速度,但會帶來導致段錯誤并降低JVM的潛力。 Agrona的緩沖區使您可以選擇通過命令行屬性agrona.disable.bounds.checks禁用邊界檢查,但默認情況下是邊界檢查。 這意味著它們的使用是安全的,但是如果對經過測試的代碼進行應用程序性能分析確定范圍檢查是瓶頸,則可以將其刪除。
結論
Agrona的緩沖區使我們可以輕松使用offheap內存,而不受Java現有字節緩沖區強加給我們的限制。 我們正在繼續擴展可從maven central下載的庫。
感謝Mike Barker,Alex Wilson,Benji Weber,Euan Macgregor和Matthew Cranman對本文的幫助。
翻譯自: https://www.javacodegeeks.com/2015/08/agronas-threadsafe-offheap-buffers.html
threadsafe
總結
以上是生活随笔為你收集整理的threadsafe_Agrona的Threadsafe堆缓冲区的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 控制备案管理人员(控制性备案)
- 下一篇: linux相关证书(linux相关)