精华内容
下载资源
问答
  • 引用计数

    2014-12-08 17:03:28
    引用计数中,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。最直观的垃圾收集策略是...

    在引用计数中,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。最直观的垃圾收集策略是引用计数。引用计数很简单,但是需要编译器的重要配合,并且增加了赋值函数 (mutator) 的开销(这个术语是针对用户程序的,是从垃圾收集器的角度来看的)。每一个对象都有一个关联的引用计数 —— 对该对象的活跃引用的数量。如果对象的引用计数是零,那么它就是垃圾(用户程序不可到达它),并可以回收。每次修改指针引用时(比如通过赋值语句),或者当引用超出范围时,编译器必须生成代码以更新引用的对象的引用计数。如果对象的引用计数变为零,那么运行时就可以立即收回这个块(并且减少被回收的块所引用的所有块的引用计数),或者将它放到迟延收集队列中。

    com组件将维护一个称作是引用计数的数值。当客户从组件取得一个接口时,此引用计数值将增1。当客户使用完某个接口后,组件的引用计数值将减1当引用计数值为0时,组件即可将自己从内存中删除。



    展开全文
  • 本文实例讲述了Python引用计数操作。分享给大家供大家参考,具体如下: 为了简化内存管理,Python通过引用计数机制实现了自动的垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被...
  • 自动引用计数是在Objective-C中就有的特性,用来辅助管理对象的引用,这里我们就来以实例讲解Swift中引用类型的ARC自动引用计数:
  • 引用计数算法.pdf

    2021-09-14 18:33:58
    引用计数算法.pdf
  • 该demo主要展现智能指针和引用计数的实现过程,总共两个类,一个智能指针类,一个引用计数类,另外附一份执行步骤资料
  • Netty之引用计数

    2018-07-17 10:41:32
    Netty中实现引用计数的接口是ReferenceCounted,一个实现了ReferenceCounted接口的类就具备了引用计数的能力。 当一个引用计数的对象被初始化时, 引用计数器被初始化为1。 ReferenceCounted接口中两个主要的方法:...

    Netty中实现引用计数的接口是ReferenceCounted,一个实现了ReferenceCounted接口的类就具备了引用计数的能力。
    当一个引用计数的对象被初始化时, 引用计数器被初始化为1。
    ReferenceCounted接口中两个主要的方法:
    retain()方法对引用计数加1,release()方法对引用计数减1。如果引用计数被减到0,则这个对象就将被显式的回收,此时再来访问该对象则会抛出IllegalReferenceCountException异常。

    当一个引用计数对象被初始化后,引用计数器的值为1,如图image1所示:

    当调用retain()方法,引用计数器的值加1,如图image2所示:

    当调用retain(2)方法,引用计数器的值加2,如图image3所示:

    当调用release(2)方法,引用计数器的值减2,如图image4所示:

    当调用release()方法,引用计数器的值减1,如图image5所示:

    当调用release()方法,引用计数器的值减1,当引用计数器的值变为0时,该引用计数对象将被回收,如图image6所示:

    使用不当常常会引起IllegalReferenceCountException异常,该异常的定义如下:

    public IllegalReferenceCountException(int refCnt, int increment) {
        this("refCnt: " + refCnt + ", " + (increment > 0? "increment: " + increment : "decrement: " + -increment));
    }
    

    相信这段异常,接触过netty的一定不会陌生。
    其中refCnt表示的是当前引用计数的值,increment表示要增加的计数值。

    PS:当increment大于0,则表示是在增加引用计数时出现错误,否则是在减少引用计数时出现的错误。

    该异常在retain()和release()方法中都有可能会抛出:

    • 在retain方法中
    private ReferenceCounted retain0(int increment) {
        for (;;) {
            int refCnt = this.refCnt;
            final int nextCnt = refCnt + increment;
            // 当nextCnt<=increment时,表面refCnt==0,说明该对象已经被回收了
            // 若此时再来增加引用计数的值,则抛出非法引用的异常
            if (nextCnt <= increment) {
                throw new IllegalReferenceCountException(refCnt, increment);
            }
            if (refCntUpdater.compareAndSet(this, refCnt, nextCnt)) {
                break;
            }
        }
        return this;
    }
    
    • 在release方法中
    private boolean release0(int decrement) {
        for (;;) {
            int refCnt = this.refCnt;
            // 由于decrement最小为1,要满足refCnt<1成立,则refCnt==0,则说明该对象已经被回收了
            // 若此时再来减少引用计数的值,则抛出非法引用的异常
            if (refCnt < decrement) {
                throw new IllegalReferenceCountException(refCnt, -decrement);
            }
            if (refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)) {
                if (refCnt == decrement) {
                    deallocate();
                    return true;
                }
                return false;
            }
        }
    }
    

    让我来构造一个出现该异常的例子,举例说明一下:
    调用write()方法引起的引用计数异常
    一个简单的服务端demo如下,该服务端实现的功能很简单,往前端输出一段json字符串:{"echo":"hello,netty"}

    public class QueenServerHandler extends ChannelInboundHandlerAdapter {
        private static final String CONTENT_TYPE_JSON = "application/json;charset=UTF-8";
        private ChannelHandlerContext ctx;
        private static final ByteBuf BUF = Unpooled.copiedBuffer("{\"echo\":\"hello,netty\"}",CharsetUtil.UTF_8);
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            this.ctx = ctx;
            response(BUF);
        }
        private void response(ByteBuf buf){
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf);
            response.headers().add(HttpHeaderNames.CONTENT_TYPE, CONTENT_TYPE_JSON);
            writeResponse(response);
        }
        private void writeResponse(Object response){
            ChannelFuture future = ctx.channel().writeAndFlush(response);
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }
    

    该代码之后,在浏览器上发起请求,第一次系统将正常返回{"echo":"hello,netty"}的内容,从第二次开始请求时,服务端将抛出下面的异常,如图image8所示:

    从异常抛出的信息:decrement: 1可以知道,应该是在调用release()方法时抛出的错。
    从异常的堆栈中可以发现,是在调用write()方法时出现的错,在MessageToMessageEncoder.write()的方法中,发现了调用release的代码,如图image9所示:

    所以到这里,异常出现的原因就很清楚了:
    该ByteBuf对象是一个类变量:private static final ByteBuf BUF;,第一次调用release时已经成功将BUF对象回收了,之后再次调用release时,就会抛出IllegalReferenceCountException异常了。
    知道原因之后,解决的方法就很简单了,有两种方法:

    • 1.将BUF对象改为局部变量,每次write的时候都创建一个新的BUF对象,之后每次再调用release就不会有问题了。
    • 2.每次使用时获取BUF的一个拷贝,用BUF.copy()来返回一个新的ByteBuf对象
    展开全文
  • 引用计数算法

    千次阅读 2019-08-22 16:18:03
    相比于前面三种垃圾收集算法,引用计数算法算是实现最简单的了,它只需要一个简单的递归即可实现。现代编程语言比如Lisp,Python,Ruby等的垃圾收集算法采用的就是引用计数算法。现在就让我们来看下引用计数算法...

    前言

    相比于前面三种垃圾收集算法,引用计数算法算是实现最简单的了,它只需要一个简单的递归即可实现。现代编程语言比如Lisp,Python,Ruby等的垃圾收集算法采用的就是引用计数算法。现在就让我们来看下引用计数算法(reference counting)是如何工作的。

    算法原理

    引用计数算法很简单,它实际上是通过在对象头中分配一个空间来保存该对象被引用的次数。如果该对象被其它对象引用,则它的引用计数加一,如果删除对该对象的引用,那么它的引用计数就减一,当该对象的引用计数为0时,那么该对象就会被回收。

    比如说,当我们编写以下代码时,

    String p = new String("abc")
    

    abc这个字符串对象的引用计数值为1.

     

     

    而当我们去除abc字符串对象的引用时,则abc字符串对象的引用计数减1

    p = null
    

    由此可见,当对象的引用计数为0时,垃圾回收就发生了。这跟前面三种垃圾收集算法不同,前面三种垃圾收集都是在为新对象分配内存空间时由于内存空间不足而触发的,而且垃圾收集是针对整个堆中的所有对象进行的。而引用计数垃圾收集机制不一样,它只是在引用计数变化为0时即刻发生,而且只针对某一个对象以及它所依赖的其它对象。所以,我们一般也称呼引用计数垃圾收集为直接的垃圾收集机制,而前面三种都属于间接的垃圾收集机制。

    而采用引用计数的垃圾收集机制跟前面三种垃圾收集机制最大的不同在于,垃圾收集的开销被分摊到整个应用程序的运行当中了,而不是在进行垃圾收集时,要挂起整个应用的运行,直到对堆中所有对象的处理都结束。因此,采用引用计数的垃圾收集不属于严格意义上的"Stop-The-World"的垃圾收集机制。这个也可以从它的伪代码实现中看出:

    New(): //分配内存
        ref <- allocate()
        if ref == null
            error "Out of memory"
        rc(ref) <- 0  //将ref的引用计数(reference counting)设置为0
        return ref
    
    atomic Write(dest, ref) //更新对象的引用
        addReference(ref)
        deleteReference(dest)
        dest <- ref
    
    addReference(ref):
        if ref != null
            rc(ref) <- rc(ref)+1
            
    deleteReference(ref):
        if ref != null
            rc(ref) <- rc(ref) -1
            if rc(ref) == 0 //如果当前ref的引用计数为0,则表明其将要被回收
                for each fld in Pointers(ref)
                    deleteReference(*fld)
                free(ref) //释放ref指向的内存空间
    

    对于上面的伪代码,重点在于理解两点,第一个是当对象的引用发生变化时,比如说将对象重新赋值给新的变量等,对象的引用计数如何变化。假设我们有两个变量p和q,它们分别指向不同的对象,当我们将他们指向同一个对象时,下面的图展示了p和q变量指向的两个对象的引用计数的变化。

    String p = new String("abc")
    String q = new String("def")
    p = q
    

    当我们执行代码p=q时,实际上相当于调用了伪代码中的Write(p,q), 即对p原先指向的对象要进行deleteReference()操作 - 引用计数减一,因为p变量不再指向该对象了,而对q原先指向的对象要进行addReference()操作 - 引用计数加一。

    第二点需要理解的是,当某个对象的引用计数减为0时,collector需要递归遍历它所指向的所有域,将它所有域所指向的对象的引用计数都减一,然后才能回收当前对象。在递归过程中,引用计数为0的对象也都将被回收,比如说下图中的phone和address指向的对象。

    环形数据问题

    但是这种引用计数算法有一个比较大的问题,那就是它不能处理环形数据 - 即如果有两个对象相互引用,那么这两个对象就不能被回收,因为它们的引用计数始终为1。这也就是我们常说的“内存泄漏”问题。比如下图展示的将p变量赋值为null值后所出现的内存泄漏。

    后记

    到今天为止,四种基本的垃圾收集算法就都介绍完了。每种算法都有它自己的优点和缺点。同时每种基本算法还有它自己的优化算法,但是在这里我只专注于介绍基本的原理,让大家知道它们是怎么工作的,对于它们的优化算法,大家可以自己查阅资料进行学习。后面我们会来看下这几种基本垃圾收集算法怎么组合成更加高级的垃圾收集算法,比如说分代垃圾收集算法等。

     

    展开全文
  • 在对象内部保存一个用来表示被引用计数的数字,init、new 和 copy 都会让引用计数 +1,调用 release 让引用计数 -1。当计数等于 0 的时候,系统调用 dealloc 方法来销毁对象。 引用计数分为自动引用计数(ARC : ...

    一、简介

    ① 引用计数概念
    • OC 在创建对象时,不会直接返回该对象,而是返回一个指向对象的指针。
    • OC 在内存管理上采用了引用计数,它是一个简单而有效管理对象生命周期的方式。
    • 在对象内部保存一个用来表示被引用计数的数字,init、new 和 copy 都会让引用计数 +1,调用 release 让引用计数 -1。当计数等于 0 的时候,系统调用 dealloc 方法来销毁对象。
    • 引用计数分为自动引用计数(ARC : Automatic Reference Counting)和手动引用计数(MRC : Manual Reference Counting)。
    ② 引用计数原理

    在这里插入图片描述

    ③ 引用计数计算
    • 指针赋值时,retainCount 不会自动增加,如下所示:
    	A *a = [
    展开全文
  • python 引用计数问题

    千次阅读 2019-04-21 15:25:35
    文章目录对象的引用计数+1的情况:对象被创建对象被引用对象被作为参数,传入到一个函数中对象作为一个元素,存储在容器中对象的引用计数-1的情况:对象的别名被赋予新的对象对象的别名被显式销毁一个对象离开它的...
  • C++引用计数

    千次阅读 2018-05-08 18:19:22
    引用计数: 当多个对象同时使用一个相同对象的资源时,会发生两种情况: ①浅拷贝时,虽然节约资源,但是释放的时候会出现问题。②深拷贝时,虽然释放不会出现问题,但是浪费了资源。为了两者都兼容,出现了引用计数。#...
  • 本篇文章是对PHP中的引用计数机制进行了详细的分析介绍,需要的朋友参考下
  • 1.引用计数的思考方式 自己生成的对象,自己持有 非自己生成的对象,自己也能持有 不在需要自己持有的对象时释放 非自己持有的对象无法释放 2.引用计数的实现 1.alloc方法 + alloc + allocWithZone: class_...
  • 下面小编就为大家带来一篇详谈swift内存管理中的引用计数。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • COM-引用计数

    2014-02-18 11:15:57
    COM笔记-引用计数 源码 vc6.0 平台
  • GC-引用计数

    千次阅读 2019-04-08 21:16:19
    GC-引用计数法 GC:释放怎么都无法被引用的对象的机制。 引用计数法在对象的元数据区,加入了计数器,用于表示当前对象被引用了多少次。 引用计数法与其他GC算法相比,在于GC的的调用时机:GC标记-清除算法是在没有...
  • 主要介绍了C++浅拷贝与深拷贝及引用计数分析的相关资料,需要的朋友可以参考下
  • 引用计数的实现,c++源码实现,工程可编译,利用模板实现的,项目中可直接使用。部分代码是从webkit中引用计数直接引用过来的
  • alloc 开辟内存空间, 并且将对象的引用计数由0变1 retain 将对象的引用计数加1 release 将对象的引用计数立即减1 autorelease 会将声明为autorelease的对象放入到离他最近的自动释放池中, 当自动释放池销毁时, 会向...
  • com关于引用计数

    千次阅读 2014-07-18 09:25:31
    实现引用计数并不难,但在什么层次上进行引用计数呢? 按照com规范,一个com组件可以实现多个com对象,并且每个com对象又可以支持多个com接口,这种层次结构为我们实现引用计数提供了多种选择方案。我们可以...
  • 引用计数法 关于引用计数法,我们可以先看一段wiki上的描述: As a collection algorithm, reference counting tracks, for each object, a count of the number of references to it held by other objects. If ...
  • Python中的垃圾回收算法是采用引用计数, 当一个对象的引用计数为0时, Python的垃圾回收机制就会将对象回收 复制 引用计数 Python使用引用计数追踪内存中的对象,当对象的引用计数变为0,它将被垃圾回收 ...
  • 自动引用计数 分为: 自动引用计数概念 引用计数策略 如何解决循环引用 闭包的循环引用
  • linux 查看文件引用计数

    千次阅读 2019-01-11 14:09:51
    在对文件操作的系统调用接口,并没有提供获取对文件引用计数的信息,所有想要获取此信息,有两种方法:  1.在内核中添加一个系统调用.将内核中文件的引用count计数返回到应用层,这种比较麻烦.不推荐  2....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 237,645
精华内容 95,058
关键字:

引用计数