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. java 中几种常用数据结构

    Java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类. 一.几个常用类的区别 1.A ...

  2. Disconf 学习系列之Disconf 的模块架构图

    不多说,直接上干货!  Disconf 的模块架构主要包括: Disconf-Tools . Disconf-Web. Disconf-client 和  Disconf-Core. 每个模块的简单介 ...

  3. 打包命令tar

    tar是linux下最常用的打包命令,使用tar打出来的包我们常称为tar包,tar包文件的命令通常都是以.tar结尾的,也有.gz或.bz2结尾的. 1 常用参数 -c,--create # 新建打 ...

  4. 使用DAO模式开发宠物管理系统---hellokitty

    宠物有狗和企鹅. 狗的属性有:编号.名称.亲密值.健康值.品种.所属主人编号. 企鹅的属性有:编号.名称.亲密值.健康值.性别.所属主人编号. 该系统中主人可以领养宠物,主人的属性有:编号.用户名.密 ...

  5. nginx 学习笔记(1) nginx安装

    1.nginx安装 根据操作系统的不同,nginx的安装方式也不相同. 1.1 对linux系统来说,nginx.org提供了nginx安装包.http://nginx.org/en/linux_pa ...

  6. oracle 执行的时候,显式输出结果!: set serveroutput on;

  7. 【转】CSS3的calc()使用——精缩版

    问题:在制作页面的时候,总会碰到有的元素是100%的宽度.如果元素宽度是100%时,只要在元素中添加了border,padding,margin任何一值,都将会把元素盒子撑破(标准模式下,除IE怪异模 ...

  8. UIKit 框架之UITableView一

    UITableView在开发中是用的最多的控件,它包含两个代理:UITableViewDataSource,UITableViewDelegate,先熟悉下API 1.初始化 - (instancet ...

  9. Android 蓝牙操作详解

    1.启用蓝牙并使设备处于可发现状态    1.1 在使用BluetoothAdapter类的实例进操作之前,应启用isEnable()方法检查设备是否启用了蓝牙适配器.       // 使用意图提示 ...

  10. Angular2入门教程-2 实现TodoList App

    最近在学习<Angular从零到一>(机械工业出版社) 遇到一些问题,书中讲的不明白,在网上找了一些,资源很多,也有很多前人的经验 https://blog.csdn.net/ztguan ...