lock free数据结构一般来说拥有比基于lock实现的数据结构更高的性能,但是其实现比基于lock的实现更为复杂,需要处理的难题包括预防ABA问题,内存如何重用和回收等。通常,最简单最有效的处理ABA问题的方法是在目标内存区域加入一个tag,每次目标内存区域被更新或者被重用时增加tag。线程最后一次读取目标内存区域后tag没有改变,CAS操作才能成功。比如对于无锁链表来说,目标内存区域就是链表节点。

但是,在目标内存区域中包含tag这种方法,当所有线程都不再需要使用某块内存区域时,没有机制可以检测。这也就导致这块内存区域不能被释放给系统供其他模块使用。hazard pointer可以用来解决这个问题。

hazard pointer的思想:每个线程可以有多个hazard pointer,和实现的lockfree数据结构相关,这些hazard pointer都会被记录到一个全局数组。线程私有的hazard pointer只能被自己修改,但是可以被其它所有线程读。比如5个线程,每个线程3个hazard pointer,那么全局数组有15个元素。一个线程操作无锁数据结构时,先将当前线程要访问的并且可能被别的线程销毁的目标内存区域的指针放在一个全局的地方,然后再检查一下这个指针是否有效,如果有效,后续就可以安全的读写目标内存区域。怎么判断有效?对于不同的数据结构来说,判断的方法不同,后续有例子。当一个线程想回收线程局部freelist中的内存区域时,首先会遍历全局hazard pointer数组,如果freelist中的目标内存区域的指针不在全局hazard pointer 数组中,说明所有线程都不会访问这个内存区域,那么这个线程就可以将这个目标内存区域释放给OS或者给其它模块使用。

以lock free stack为例:

由于Push操作不会访问可能需要被free的节点的内容,所以不需要修改

重点关注Pop操作:

由于第4行会通过指针t来访问t指向的内存区域的内容,所以在第2行,就把t这个指针保护起来,放入这个线程所属的hazard pointer中(对于lock free stack来说,每个线程只需要一个hazard pointer),放入后,再通过第3行来判断t是否有效,如果t不再是栈顶,说明在第1行和第3行之间,别的线程已经成功pop了栈顶,重试。如果t仍然是栈顶,那么第4步用指针t来访问t指向的内存区域中的变量next是安全的,因为t在之前已经放入了hazard pointer中,别的线程在全局hazard pointer数组中能够找到这个hazard pointer,就不会释放这个节点。while 循环退出,所以pop成功,然后将自己的hazard pointer置NULL,表示本线程后续不会再访问这个节点。

参考资料:

Safe Memory Reclamation for Dynamic Lock-Free Objects Using Atomic Reads and Writes

High Performance Dynamic Lock-Free Hash Tables and List-Based Sets

http://en.wikipedia.org/wiki/ABA

Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects

lock free数据结构内存回收技术-hazard pointer的更多相关文章

  1. Btree并发内存回收

    在并发写Btree原理剖析 一文中提到,节点内存回收有可能导致内存突增以及影响写性能.本文将阐述最近对内存回收的改进,多线程可并行回收内存. 回收策略 采用基于版本的机制,Btree全局维护一个版本号 ...

  2. 《深入理解Java虚拟机》学习笔记之内存回收

    垃圾收集(Garbage Collection,GC)并不是Java语言的半生产物,事实上GC历史远比Java久远,真正使用内存动态分配和垃圾收集技术的语言是诞生于1960年的Lisp语言.经过半个世 ...

  3. 风险指针(Hazard Pointer) 内存空间共享模型

    WiredTiger是一种高性能的开源存储引擎,现已在MongoDB中作为内模式应用.WiredTiger支持行存储.列存储两种存储模式,采用LSM Tree方式进行索引记录 WiredTiger支持 ...

  4. Java技术专题之JVM逻辑内存回收机制研究图解版

    一.引言 JVM虚拟机内存回收机曾迷惑了不少人,文本从JVM实现机制的角度揭示JVM内存回收的原理和机制. 一.Java平台逻辑架构 二.JVM物理结构 通过从JVM物理结构图我们可以看到: 1.JV ...

  5. (转)从内存管 理、内存泄漏、内存回收探讨C++内存管理

    http://www.cr173.com/html/18898_all.html 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟 ...

  6. 实现无锁的栈与队列(5):Hazard Pointer

    两年多以前随手写了点与 lock free 相关的笔记:1,2,3,4,质量都不是很高其实(读者见谅),但两年来陆陆续续竟也有些阅读量了(可见剑走偏锋的技巧是多容易吸引眼球).笔记当中在解决内存释放和 ...

  7. 【转】图片缓存之内存缓存技术LruCache、软引用 比较

    每当碰到一些大图片的时候,我们如果不对图片进行处理就会报OOM异常,这个问题曾经让我觉得很烦恼,后来终于得到了解决,那么现在就让我和大家一起分享一下吧.这篇博文要讲的图片缓存机制,我接触到的有两钟,一 ...

  8. JVM内存回收机制——哪些内存需要被回收(JVM学习系列2)

    上一篇文章中讨论了Java内存运行时的各个区域,其中程序计数器.虚拟机栈.本地方法栈随线程生灭,且创建时需要多少内存,基本上在译期间就决定的了,所以在内存回收时无需特殊的关注.而堆和方法区则不同,首先 ...

  9. JVM垃圾回收机制与内存回收

    暂时转于:https://blog.csdn.net/qq_27035123/article/details/72857739 垃圾回收机制 GC是垃圾回收机制,java中将内存管理交给垃圾回收机制, ...

随机推荐

  1. php如何使用rabbitmq实现发布消息和消费消息(tp框架)(第一篇)

    1,默认已经安装好了rabbitmq: 参考 http://www.cnblogs.com/spicy/p/7017603.html 2,安装rabbitmq客户端: 方法1: pecl 扩展安装  ...

  2. postman—集成到jenkins

    前言 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 将postman导出的脚本,持续集成到 ...

  3. IntelliJ IDEA的黑白色背景切换(Ultimate和Community版本皆通用)

    不多说,直接上干货! IntelliJ IDEA的黑白色背景切换 File    ->   Setting    ->  Editor     ->   Colors & F ...

  4. 在k8s中搭建可解析hostname的DNS服务

    2016-01-25更新 上篇文章总结k8s中搭建hbase时,遇到Pod中hostname的DNS解析问题,本篇将通过修改kube2sky源码来解决这个问题. 1 前言 kube2sky在Githu ...

  5. java学习-get和post请求

    摘要 看完本文可以知道,使用java原生编写get/post请求的步骤,进行网络请求时应该注意的地方. 这里使用java自带的HttpUrlConnection对象进行网络请求, 请求步骤大致分为五步 ...

  6. Linux-(kill,wc,killall,ln,cal,date)

    kill命令 1.命令格式: kill [参数] [进程号] 2.命令功能: 发送指定的信号到相应进程.不指定型号将发送SIGTERM(15)终止指定进程.如果仍无法终止该程序可用“-KILL” 参数 ...

  7. 小程序之底部tabBar

    用法简介: 1.app.json中配置下tabBar即可,注意tabBar至少需要两个最多五个Item选项 这里简单列举一些属性值:对于tabBar整体属性设置: 对于tabBar中每个Item属性设 ...

  8. Maven 添加 Tomcat 插件

    若想在 Maven 中使用 Tomcat 服务器,需要在 pom.xml 文件中的 <build></build> 标签中添加以下代码 <!-- Maven项目编译插件 ...

  9. 问题集录--Java高级软件工程师面试考纲(转)

    如果要应聘高级开发工程师职务,仅仅懂得Java的基础知识是远远不够的,还必须懂得常用数据结构.算法.网络.操作系统等知识.因此本文不会讲解具体的技术,笔者综合自己应聘各大公司的经历,整理了一份大公司对 ...

  10. android service服务的学习

    1.Service简单概述   Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件.服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即 ...