• 引用计数器

    引用计数器

    Netty 4 引入了 引用计数器给 ByteBuf 和 ByteBufHolder(两者都实现了 ReferenceCounted 接口)

    引用计数本身并不复杂;它在特定的对象上跟踪引用的数目。实现了ReferenceCounted 的类的实例会通常开始于一个活动的引用计数器为 1。活动的引用计数器大于0的对象被保证不被释放。当数量引用减少到0,该实例将被释放。需要注意的是“释放”的语义是特定于具体的实现。最起码,一个对象,它已被释放应不再可用。

    这种技术就是诸如 PooledByteBufAllocator 这种减少内存分配开销的池化的精髓部分。

    Listing 5.16 Reference counting

    1. Channel channel = ...;
    2. ByteBufAllocator allocator = channel.alloc(); //1
    3. ....
    4. ByteBuf buffer = allocator.directBuffer(); //2
    5. assert buffer.refCnt() == 1; //3
    6. ...

    1.从 channel 获取 ByteBufAllocator

    2.从 ByteBufAllocator 分配一个 ByteBuf

    3.检查引用计数器是否是 1

    Listing 5.17 Release reference counted object

    1. ByteBuf buffer = ...;
    2. boolean released = buffer.release(); //1
    3. ...

    1.release()将会递减对象引用的数目。当这个引用计数达到0时,对象已被释放,并且该方法返回 true。

    如果尝试访问已经释放的对象,将会抛出 IllegalReferenceCountException 异常。

    需要注意的是一个特定的类可以定义自己独特的方式其释放计数的“规则”。
    例如,release() 可以将引用计数器直接计为 0 而不管当前引用的对象数目。

    谁负责 release?

    在一般情况下,最后访问的对象负责释放它。在第6章我们会解释 ChannelHandler 和 ChannelPipeline 的相关概念。