Netty源码分析-DefaultAttributeMap

 


package io.netty.util;

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * Default {@link AttributeMap} implementation which use simple synchronization per bucket to keep the memory overhead
 * as low as possible.
 */
public class DefaultAttributeMap implements AttributeMap {

	//以原子方式更新attributes变量的引用
    @SuppressWarnings("rawtypes")
    private static final AtomicReferenceFieldUpdater<DefaultAttributeMap, AtomicReferenceArray> updater =
            AtomicReferenceFieldUpdater.newUpdater(DefaultAttributeMap.class, AtomicReferenceArray.class, "attributes");

	//默认桶的大小
    private static final int BUCKET_SIZE = 4;
	
	//掩码 桶大小-1
    private static final int MASK = BUCKET_SIZE  - 1;

	//延迟初始化,节约内存
    // Initialize lazily to reduce memory consumption; updated by AtomicReferenceFieldUpdater above.
    @SuppressWarnings("UnusedDeclaration")
    private volatile AtomicReferenceArray<DefaultAttribute<?>> attributes;

    @SuppressWarnings("unchecked")
    @Override
    public <T> Attribute<T> attr(AttributeKey<T> key) {
        if (key == null) {
            throw new NullPointerException("key");
        }
        AtomicReferenceArray<DefaultAttribute<?>> attributes = this.attributes;
		
		//当attributes为空时则创建它,默认数组长度4
        if (attributes == null) {
			//没有使用ConcurrentHashMap为了节约内存
            // Not using ConcurrentHashMap due to high memory consumption.
            attributes = new AtomicReferenceArray<DefaultAttribute<?>>(BUCKET_SIZE);
			
			//原子方式更新attributes,如果attributes为null则把新创建的对象赋值
			//原子方式更新解决了并发赋值问题
            if (!updater.compareAndSet(this, null, attributes)) {
                attributes = this.attributes;
            }
        }

		//根据key计算下标
        int i = index(key);
		
		//返回attributes数组中的第一个元素
        DefaultAttribute<?> head = attributes.get(i);
		
		//头部为空说明第一次添加,这个方法可能多个线程同时调用,因为判断head全部为null
        if (head == null) {
            // No head exists yet which means we may be able to add the attribute without synchronization and just
            // use compare and set. At worst we need to fallback to synchronization and waste two allocations.
			
			//创建一个空对象为链表结构的起点
            head = new DefaultAttribute();
			
			//创建一个attr对象,把head传进去
            DefaultAttribute<T> attr = new DefaultAttribute<T>(head, key);
			
			//链表头head的next = attr
            head.next = attr;
			//attr的prev = head
            attr.prev = head;
			
			//给数组i位置赋值,这里用compareAndSet原子更新方法解决并发问题
			//只有i位置为null能够设置成功,且只有一个线程能设置成功
            if (attributes.compareAndSet(i, null, head)) {
				//设置成功后返回attr
                // we were able to add it so return the attr right away
                return attr;
            } else {
				//设置失败的,说明数组i位置已经被其它线程赋值
				//所以要把head重新赋值,不能用上面new出来的head,需要拿到之前线程设置进去的head
                head = attributes.get(i);
            }
        }
		
		//对head同步加锁
        synchronized (head) {
			//curr 赋值为head    head为链表结构的第一个变量
            DefaultAttribute<?> curr = head;
            for (;;) {
				//依次获取next
                DefaultAttribute<?> next = curr.next;
				//next==null,说明curr为最后一个元素
                if (next == null) {
					//创建一个新对象传入head和key
                    DefaultAttribute<T> attr = new DefaultAttribute<T>(head, key);
					//curr后面指向attr
                    curr.next = attr;
					//attr的前面指向curr
                    attr.prev = curr;
					//返回新对象
                    return attr;
                }
				
				//如果next的key等于传入的key,并且没有被移除
                if (next.key == key && !next.removed) {
					//这直接返回next
                    return (Attribute<T>) next;
                }
				//否则把curr变量指向下一个元素
                curr = next;
            }
        }
    }

    @Override
    public <T> boolean hasAttr(AttributeKey<T> key) {
        if (key == null) {
            throw new NullPointerException("key");
        }
		
		//attributes为null直接返回false
        AtomicReferenceArray<DefaultAttribute<?>> attributes = this.attributes;
        if (attributes == null) {
            // no attribute exists
            return false;
        }

		//计算数组下标
        int i = index(key);
		
		//获取头 为空直接返回false
        DefaultAttribute<?> head = attributes.get(i);
        if (head == null) {
            // No attribute exists which point to the bucket in which the head should be located
            return false;
        }

		//对head同步加锁
        // We need to synchronize on the head.
        synchronized (head) {
            // Start with head.next as the head itself does not store an attribute.
			//从head的下一个开始,因为head不存储元素
            DefaultAttribute<?> curr = head.next;
			
			//为null说明没有节点了
            while (curr != null) {
				//key一致并且没有被移除则返回true
                if (curr.key == key && !curr.removed) {
                    return true;
                }
				//curr指向下一个
                curr = curr.next;
            }
            return false;
        }
    }

    private static int index(AttributeKey<?> key) {
		//与掩码&运算,数值肯定<=mask 正好是数组下标
        return key.id() & MASK;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值