三色算法和SATB算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三色算法和SATB算法相关的知识,希望对你有一定的参考价值。

参考技术A

1、黑色:根对象,或者该对象与它的子对象都被扫描过(对象被标记了,且它的所有field也被标记完了)。
2、灰色:对象本身被扫描,但还没扫描完该对象中的子对象(它的field还没有被标记或标记完)。
3、白色:未被扫描对象,扫描完成所有对象之后,最终为白色的为不可达对象,既垃圾对象(对象没有被标记到)。

GC root 出发遍历heap,针对可达对象先标记白色为灰色,然后标记灰色为黑色,遍历完成之后所有可达对象都是黑色的,所有白色都是可以回收的

但是如果在标记过程中,应用程序也在运行,那么对象的指针就有可能改变。这样的话,我们就会遇到一个问题:对象丢失问题。那问题是如何产生的呢,下面来说一下。

在G1中,使用的是SATB(Snapshot-At-The-Beginning)的方式,删除的时候记录所有的对象。

1、在开始标记的时候生成一个快照图,标记存活对象。
2、在并发标记的时候,write barrier【写屏障】里把所有旧的引用所指向的对象都变成非白的。
①:对于从gray对象 移除的目标引用对象 标记为gray,将所有既将被删除的引用关系的旧引用记录下来,最后以这些旧引用为根重新扫描一遍。
②:对于black 引用的新产生的对象 标记为blcak,将所有新增的引用关系,然后根据这些引用关系为根重新扫描一遍。
3、可能存在浮动垃圾,将在下次被收集。

误标没什么关系,顶多造成浮动垃圾,在下次gc还是可以回收的,但是漏标的后果是致命的,把本应该存活的对象给回收了,从而影响的程序的正确性。

编程之法:面试和算法心得(荷兰国旗)

内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java

题目描述

拿破仑席卷欧洲大陆之后,代表自由,平等,博爱的竖色三色旗也风靡一时。荷兰国旗就是一面三色旗(只不过是横向的),自上而下为红白蓝三色。

技术分享图片

该问题本身是关于三色球排序和分类的,由荷兰科学家Dijkstra提出。由于问题中的三色小球有序排列后正好分为三类,Dijkstra就想象成他母国的国旗,于是问题也就被命名为荷兰旗问题(Dutch National Flag Problem)。

下面是问题的正规描述: 现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右,依次是一些红球、一些白球、一些蓝球。

分析与解法

初看此题,我们貌似除了暴力解决并无好的办法,但联想到我们所熟知的快速排序算法呢?

我们知道,快速排序依托于一个partition分治过程,在每一趟排序的过程中,选取的主元都会把整个数组排列成一大一小的部分,那我们是否可以借鉴partition过程设定三个指针完成重新排列,使得所有球排列成三个不同颜色的球呢?

解法一

通过前面的分析得知,这个问题类似快排中partition过程,只是需要用到三个指针:一个前指针begin,一个中指针current,一个后指针end,current指针遍历整个数组序列,当

  1. current指针所指元素为0时,与begin指针所指的元素交换,而后current++,begin++ ;
  2. current指针所指元素为1时,不做任何交换(即球不动),而后current++ ;
  3. current指针所指元素为2时,与end指针所指的元素交换,而后,current指针不动,end-- 。

为什么上述第3点中,current指针所指元素为2时,与end指针所指元素交换之后,current指针不能动呢?因为第三步中current指针所指元素与end指针所指元素交换之前,如果end指针之前指的元素是0,那么与current指针所指元素交换之后,current指针此刻所指的元素是0,此时,current指针能动么?不能动,因为如上述第1点所述,如果current指针所指的元素是0,还得与begin指针所指的元素交换。

ok,说这么多,你可能不甚明了,直接引用下gnuhpc的图,就一目了然了:

技术分享图片

public static void solution(int arr[])
    {
        int begin = 0;
        int current = 0;
        int end = arr.length-1;
        while(current<end)
        {
            if(arr[current]==0)
            {
                int temp = arr[begin];
                arr[begin] = arr[current];
                arr[current] = temp;
                begin++;
                current++;
            }
            if(arr[current]==1)
            {
                current++;
            }
            if(arr[current]==2)
            {
                int temp = arr[end];
                arr[end] = arr[current];
                arr[current] = temp;
                end--;
            }
        }
    }

 

以上是关于三色算法和SATB算法的主要内容,如果未能解决你的问题,请参考以下文章

算法分析之三色旗算法

编程之法:面试和算法心得(荷兰国旗)

经典算法-三色旗

算法--三色排序练习题

2020-10-03:java中satb和tlab有什么区别?

三色旗