netty的引用計數


netty的引用計數文檔看http://netty.io/wiki/reference-counted-objects.html

為什么會引用引用計數呢,Java中不是有gc線程幫我們回收對象嗎?我個人理解如下

1:netty為了實現zero copy使用了Direct Buffer,該buffer從Native Memory分配出來,分配和回收效率要遠低於在Java Heap上的對象,所以一般full gc來控制的,直接內存會自己檢測情況而調用system.gc(),通過使用引用計數可以自己來控制該buffer的釋放。具體看PlatformDependent.freeDirectBuffer(buffer)的實現。

這塊內容請看:http://blog.csdn.net/xieyuooo/article/details/7547435

2:netty使用了Pooled的功能。有點像c++的對象池,先分配一大塊內存,然后從里面切出一塊一塊的供你使用,引用計數為0放入pool中,供后面使用。

如果不按按引用計數規則使用這兩種對象,將會導致內存泄露。所以測試的時候需要測試下是有有內存泄漏。

 

Netty引用計數的實現在AbstractReferenceCountedByteBuf代碼里。

    private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater;

    static {
        AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> updater =
                PlatformDependent.newAtomicIntegerFieldUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
        if (updater == null) {
            updater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
        }
        refCntUpdater = updater;
    }

    private volatile int refCnt = 1;

volatile是線程可見變量,保存在Jvm的主內存中,而不是線程的工作內存里面。然后使用jdk的原子庫對引用計數進行原子更新。
AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceFieldUpdater通過反射原子更新對象的字段,被更新的字段是有要求的

1:必須是volatile類型,
2:注意訪問描述符(public ,protected ,defualt,private).
3: 只能是實例變量不能是類變量
4:對於AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long類型的字段,不能修改其包裝類型(Integer/Long)。如果要修改包裝類型就需要使用AtomicReferenceFieldUpdater

public class Updater {
    public static void main(String[] args) throws InterruptedException {
        Container c=new Container();
          for(int i=0;i<1000;i++)
          {
              Task t=new Task(c);
              t.start();
              t.join(); //join方法在start后調用,調用線程會等待被調用的線程執行完成后執行

          }
        System.out.println("============="+c.index);
    }
}

class Container{
    public volatile  int index=0;
}

class Task extends Thread {
    private AtomicIntegerFieldUpdater<Container> updater =
            AtomicIntegerFieldUpdater.newUpdater(Container.class,"index");
    private Container c;

    public Task(Container c) {
        this.c = c;
    }
    @Override
    public void run() {
        System.out.println(updater.getAndIncrement(c));
        System.out.println(updater.getAndDecrement(c));
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM