jdk 原地分析(3)java ConcurrentHashMap结构分析


1)存储结构:存储结构和hashmap相似,但是添加一个root级别的锁。
链表:
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    volatile V val;
    volatile Node<K,V> next;

    Node(int hash, K key, V val, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.val = val;
        this.next = next;
    }
树:
static final class TreeNode<K,V> extends Node<K,V> {
    TreeNode<K,V> parent;  // red-black tree links
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // needed to unlink next upon deletion
    boolean red;

    TreeNode(int hash, K key, V val, Node<K,V> next,
             TreeNode<K,V> parent) {
        super(hash, key, val, next);
        this.parent = parent;
    }

锁根
/**
 * TreeNodes used at the heads of bins. TreeBins do not hold user
 * keys or values, but instead point to list of TreeNodes and
 * their root. They also maintain a parasitic read-write lock
 * forcing writers (who hold bin lock) to wait for readers (who do
 * not) to complete before tree restructuring operations.
 */
static final class TreeBin<K,V> extends Node<K,V> {
    TreeNode<K,V> root;
    volatile TreeNode<K,V> first;
    volatile Thread waiter;
    volatile int lockState;
    // values for lockState
    static final int WRITER = 1; // set while holding write lock
    static final int WAITER = 2; // set when waiting for write lock
    static final int READER = 4; // increment value for setting read lock

2)put,里面大量使用unsafe 类,乐观写比同步锁要快很多。concurrent相对于hashmap 就是因为多了 乐观锁的操作
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
    return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}
static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                    Node<K,V> c, Node<K,V> v) {
    return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
}
因为这些东西,使得线程变的安全,而且乐观锁比悲观锁的性能好好很多。
   
   
  1. /** Implementation for put and putIfAbsent */
  2. final V putVal(K key, V value, boolean onlyIfAbsent) {
  3. if (key == null || value == null) throw new NullPointerException();
  4.         
  5. int hash = spread(key.hashCode());
  6. int binCount = 0;
  7. for (Node<K,V>[] tab = table;;) {
  8. Node<K,V> f; int n, i, fh;
  9. if (tab == null || (n = tab.length) == 0)
  10. tab = initTable();
  11.             //分支没有数据,直接写就行。
  12. else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
  13. if (casTabAt(tab, i, null,
  14. new Node<K,V>(hash, key, value, null)))
  15. break; // no lock when adding to empty bin
  16. }
  17.             //数据多了之后可以在移动,
  18. else if ((fh = f.hash) == MOVED)
  19. tab = helpTransfer(tab, f);
  20. else {
  21. V oldVal = null;
  22. synchronized (f) {
  23. if (tabAt(tab, i) == f) {
  24. if (fh >= 0) {
  25. binCount = 1;
  26. for (Node<K,V> e = f;; ++binCount) {
  27. K ek;
  28. if (e.hash == hash &&
  29. ((ek = e.key) == key ||
  30. (ek != null && key.equals(ek)))) {
  31. oldVal = e.val;
  32. if (!onlyIfAbsent)
  33. e.val = value;
  34. break;
  35. }
  36. Node<K,V> pred = e;
  37. if ((e = e.next) == null) {
  38. pred.next = new Node<K,V>(hash, key,
  39. value, null);
  40. break;
  41. }
  42. }
  43. }
  44. else if (f instanceof TreeBin) {
  45. Node<K,V> p;
  46. binCount = 2;
  47. if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
  48. value)) != null) {
  49. oldVal = p.val;
  50. if (!onlyIfAbsent)
  51. p.val = value;
  52. }
  53. }
  54. }
  55. }
  56. if (binCount != 0) {
  57. if (binCount >= TREEIFY_THRESHOLD)
  58. treeifyBin(tab, i);
  59. if (oldVal != null)
  60. return oldVal;
  61. break;
  62. }
  63. }
  64. }
  65. addCount(1L, binCount);
  66. return null;
  67. }









1)存储结构:存储结构和hashmap相似,但是添加一个root级别的锁。
链表:
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    volatile V val;
    volatile Node<K,V> next;

    Node(int hash, K key, V val, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.val = val;
        this.next = next;
    }
树:
static final class TreeNode<K,V> extends Node<K,V> {
    TreeNode<K,V> parent;  // red-black tree links
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // needed to unlink next upon deletion
    boolean red;

    TreeNode(int hash, K key, V val, Node<K,V> next,
             TreeNode<K,V> parent) {
        super(hash, key, val, next);
        this.parent = parent;
    }

锁根
/**
 * TreeNodes used at the heads of bins. TreeBins do not hold user
 * keys or values, but instead point to list of TreeNodes and
 * their root. They also maintain a parasitic read-write lock
 * forcing writers (who hold bin lock) to wait for readers (who do
 * not) to complete before tree restructuring operations.
 */
static final class TreeBin<K,V> extends Node<K,V> {
    TreeNode<K,V> root;
    volatile TreeNode<K,V> first;
    volatile Thread waiter;
    volatile int lockState;
    // values for lockState
    static final int WRITER = 1; // set while holding write lock
    static final int WAITER = 2; // set when waiting for write lock
    static final int READER = 4; // increment value for setting read lock

2)put,里面大量使用unsafe 类,乐观写比同步锁要快很多。concurrent相对于hashmap 就是因为多了 乐观锁的操作
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
    return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}
static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                    Node<K,V> c, Node<K,V> v) {
    return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
}
因为这些东西,使得线程变的安全,而且乐观锁比悲观锁的性能好好很多。
    
    
  1. /** Implementation for put and putIfAbsent */
  2. final V putVal(K key, V value, boolean onlyIfAbsent) {
  3. if (key == null || value == null) throw new NullPointerException();
  4.         
  5. int hash = spread(key.hashCode());
  6. int binCount = 0;
  7. for (Node<K,V>[] tab = table;;) {
  8. Node<K,V> f; int n, i, fh;
  9. if (tab == null || (n = tab.length) == 0)
  10. tab = initTable();
  11.             //分支没有数据,直接写就行。
  12. else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
  13. if (casTabAt(tab, i, null,
  14. new Node<K,V>(hash, key, value, null)))
  15. break; // no lock when adding to empty bin
  16. }
  17.             //数据多了之后可以在移动,
  18. else if ((fh = f.hash) == MOVED)
  19. tab = helpTransfer(tab, f);
  20. else {
  21. V oldVal = null;
  22. synchronized (f) {
  23. if (tabAt(tab, i) == f) {
  24. if (fh >= 0) {
  25. binCount = 1;
  26. for (Node<K,V> e = f;; ++binCount) {
  27. K ek;
  28. if (e.hash == hash &&
  29. ((ek = e.key) == key ||
  30. (ek != null && key.equals(ek)))) {
  31. oldVal = e.val;
  32. if (!onlyIfAbsent)
  33. e.val = value;
  34. break;
  35. }
  36. Node<K,V> pred = e;
  37. if ((e = e.next) == null) {
  38. pred.next = new Node<K,V>(hash, key,
  39. value, null);
  40. break;
  41. }
  42. }
  43. }
  44. else if (f instanceof TreeBin) {
  45. Node<K,V> p;
  46. binCount = 2;
  47. if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
  48. value)) != null) {
  49. oldVal = p.val;
  50. if (!onlyIfAbsent)
  51. p.val = value;
  52. }
  53. }
  54. }
  55. }
  56. if (binCount != 0) {
  57. if (binCount >= TREEIFY_THRESHOLD)
  58. treeifyBin(tab, i);
  59. if (oldVal != null)
  60. return oldVal;
  61. break;
  62. }
  63. }
  64. }
  65. addCount(1L, binCount);
  66. return null;
  67. }







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值