threadsafe_Agrona的Threadsafe堆缓冲区

threadsafe

这篇博客文章通过说明我们如何轻松访问线程内存来进行线程安全操作,继续了我在Agrona库上进行的系列文章 。 在继续讨论这是一个相当高级的主题之前,我可能应该警告一下,并且我不尝试解释诸如内存屏障之类的概念,仅概述API的功能。

ByteBuffer的不足

Java提供了一个字节缓冲区类来包装offheap和onheap内存。 字节缓冲区在Java网络堆栈中专门用作从中读取或写入数据的位置。

那么字节缓冲区有什么问题呢? 好吧,因为它们针对用例,所以它们不提供对原子操作之类的支持。 如果要编写可从不同进程同时访问的非堆数据结构,则字节缓冲区无法满足您的需求。 您可能要编写的那种库的一个示例是一个消息队列,一个进程将读取该消息,而另一个进程将写入该消息队列。

Agrona的缓冲器

Agrona提供了几种缓冲区类和接口来克服这些缺陷。 Aeron和SBE库都使用这些缓冲区。

  1. DirectBuffer –顶级接口,可从缓冲区读取值。
  2. MutableDirectBuffer –扩展DirectBuffer添加操作以写入缓冲区。
  3. AtomicBuffer –不,它不是核动力的MutableDirectBuffer ! 该接口添加了原子操作以及比较和交换语义。
  4. UnsafeBuffer –默认实现。 名称unsafe并不意味着不应该使用该类,只是其支持实现使用sun.misc.Unsafe

拆分缓冲区而不是分配单个类的决定是出于希望限制不同系统组件对缓冲区的访问权限的考虑。 如果一个类只需要从一个缓冲区中读取,则不应允许它通过使缓冲区发生突变而将错误引入系统。 同样,不允许设计为单线程的组件使用Atomic操作。

包装一些内存

为了能够使用缓冲区执行任何操作,您需要告诉它缓冲区的起始位置! 此过程称为包装基础内存。 所有包装内存的方法都称为wrap并且可以包装byte[]ByteBufferDirectBuffer 。 您还可以指定用于包装数据结构的偏移量和长度。 例如,这里是包装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[]ByteBufferDirectBuffer 。 例如,这是将数据读入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);

并发操作

intlong值也可以使用内存排序语义进行读取或写入。 后缀为Ordered方法保证它们最终将被设置为所讨论的值,并且该值最终将在另一个对该值进行易失性读取的线程中可见。 换句话说, putLongOrdered自动执行存储存储内存屏障 。 get*Volatileput*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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337490.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言编程中错误异常该如何统一处理?1.8万字总结

点击蓝字关注我们本文主要总结嵌入式系统C语言编程中,主要的错误处理方式。一、错误概念1.1 错误分类从严重性而言,程序错误可分为致命性和非致命性两类。对于致命性错误,无法执行恢复动作,最多只能在用户屏幕上打印出错消息或将其…

Python3实现最小栈

Python3实现最小栈原题 https://leetcode-cn.com/problems/min-stack/ 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。 push(x) – 将元素 x 推入栈中。 pop() – 删除栈顶的元素。 top() – 获取栈顶元素。 getMin…

pycharm remote 远程项目 同步 本地_利器:PyCharm本地连接服务器搭建深度学习实验环境的三重境界...

作为实验室社畜,常需要在本地使用Pycharm写代码,然后将代码同步到服务器上,使用远程登录服务器并运行代码做实验。这其中有很多事情如果没有好的工具,做起来会非常麻烦。比如如何快速同步本地与服务器的代码?如何优雅地…

防御性编程技巧

点击蓝字关注我们在防御性编程的大框架之下,有许多常识性的规则。人们在想到防御性编程的时候,通常都会想到“断言”,这没有错。我们将在后面对此进行讨论。但是,还是有一些简单的编程习惯可以极大地提高代码的安全性。尽管看上去…

unity创建和销毁对象_如何创建和销毁对象

unity创建和销毁对象本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的旅程! 在这里查看 &…

Python3实现打家劫舍问题

Python3实现打家劫舍问题原题 https://leetcode-cn.com/problems/house-robber/ 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同…

cookie无法读取bdstoken_第二章(第12节):cookie操作

有时候我们需要验证浏览器中 cookie 是否正确,因为基于真实 cookie 的测试是无法通过白盒和集成测试进行的。WebDriver 提供了操作 cookie 的相关方法,可以读取、添加和删除 cookie信息。WebDriver 操作 cookie 的方法:get_cookies()&#xf…

js 序列化内置对象_内置序列化技术

js 序列化内置对象本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的旅程! 在这里查看 &#x…

C++ 基本的输入输出

点击蓝字关注我们C 标准库虽然提供了一组丰富的输入/输出功能,但是本章只讨论 C 编程中最基本和最常见的 I/O 操作。C 的 I/O 发生在流中,流是字节序列。如果字节流是从设备(如键盘、磁盘驱动器、网络连接等)流向内存,…

Python3有效括号问题

Python3有效括号问题原题 https://leetcode-cn.com/problems/valid-parentheses/ 给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。 有效字符串需满足: 左…

http 和 https_HTTPS与HTTP区别

HTTPS与HTTP的认识:HTTP 加密 认证 完整性保护 HTTPSHTTP的全称是 Hypertext Transfer Protocol Vertion (超文本传输协议)HTTPS: HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议。HTTPS和HTTP的区别:HTTPS协议需要到ca申…

C语言指针的自我介绍(你了解我吗?了解多少?)

点击蓝字关注我们hey! Ladies and Gentlemen.😁欢迎大家来看望我,对,我就是指针(pointer),被很多人吐槽😔,也被人说好。我希望大家了解过我以后,能够爱上我😘。大家在了解我之前 &am…

Python3最长连续递增序列问题

Python3最长连续递增序列问题原题 https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/ 题目: 给定一个未经排序的整数数组,找到最长且连续的的递增序列。 示例 1: 输入: [1,3,5,4,7] 输出: 3 解释: 最长连续递增序列是 [1…

访问nfs_通过NFS访问编年引擎

访问nfs总览 编年史引擎是数据虚拟化层。 它抽象化了访问,操作和订阅各种数据源的复杂性,因此该数据的用户无需知道实际存储数据的方式或位置。 这意味着该数据可以在系统之间迁移或以更有效的方式存储,但对于开发人员来说使用起来很复杂。 …

flex 解析json文件_使用 Python 处理 JSON 格式的数据 | Linux 中国

如果你不希望从头开始创造一种数据格式来存放数据,JSON 是一个很好的选择。如果你对 Python 有所了解,就更加事半功倍了。下面就来介绍一下如何使用 Python 处理 JSON 数据。-- Seth KenlonJSON 的全称是 JavaScript 对象表示法JavaScript Object Notati…

【C语言】指针进阶第一站:字符指针 typedef关键字!

点击蓝字关注我们简单回顾一下指针的概念内存会划分以字节为单位的空间,每一个字节都有一个编号(地址/指针)指针变量可以存放这个地址/指针注:我们日常所说的指针,一般是指针变量下面让我们坐上指针进阶的直通车&#…

漫反射 高光反射_如何有效地使用反射

漫反射 高光反射本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的旅程! 在这里查看 &#xff…

python编译helloworld_python3学习笔记--001--python HelloWorld

python默认使用UTF-8编码 一个python3版本的HelloWorld代码如下: #!/usr/bin/env python print (Hello World!) 如果此python脚本文件名为:hello.py,则运行此脚本文件的方法有两种: 1、python hello.py [laolanglocalhost python]…

漫谈 C++:良好的编程习惯与编程要点

点击蓝字关注我们以良好的方式编写C class假设现在我们要实现一个复数类complex,在类的实现过程中探索良好的编程习惯。① Header(头文件)中的防卫式声明complex.h: # ifndef __COMPLEX__ # define __COMPLEX__ class complex {} # endif防止头文件的内容被多次包含…

Python3只出现一次数字

Python3只出现一次数字原题 https://leetcode-cn.com/problems/single-number/ 题目: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时…