java 自己动手实现一个分布式系统 之 Netty篇 引用计数

netty为什么要使用引用计数---------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));
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yann.bai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值