From eb23c34734506b1a1a4faaaaf4cdf6adbecd3254 Mon Sep 17 00:00:00 2001 From: chenjing Date: Sun, 29 Mar 2020 22:36:38 +0800 Subject: [PATCH] 83 --- second/week_04/83/concurrent.md | 92 +++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 second/week_04/83/concurrent.md diff --git a/second/week_04/83/concurrent.md b/second/week_04/83/concurrent.md new file mode 100644 index 0000000..6227033 --- /dev/null +++ b/second/week_04/83/concurrent.md @@ -0,0 +1,92 @@ +明天补完 + +# CopyOnWriteArrayList +CopyOnWriteArrayList是ArrayList的线程安全版本,内部也是通过数组实现,每次对数组的修改都完全拷贝一份新的数组来修改,修改完了再替换掉老数组,这样保证了只阻塞写操作,不阻塞读操作,实现读写分离。 +```java +//属性 + /** The lock protecting all mutators 用于修改时加锁*/ + final transient ReentrantLock lock = new ReentrantLock(); + /** 真正存储元素的地方,accessed only via getArray/setArray. */ + private transient volatile Object[] array; + +//浅拷贝构造 +public CopyOnWriteArrayList(Collection c) { + Object[] elements; + if (c.getClass() == CopyOnWriteArrayList.class) + elements = ((CopyOnWriteArrayList)c).getArray(); + else { +// 不是CopyOnWriteArrayList类型则调用其toArray()方法将集合元素转化为数组 + elements = c.toArray(); + // c.toArray might (incorrectly) not return Object[] (see 6260652) + if (elements.getClass() != Object[].class) + elements = Arrays.copyOf(elements, elements.length, Object[].class); + } + setArray(elements); + } +``` +添加一个元素到末尾 +```java + /** + * Appends the specified element to the end of this list. + * + * @param e element to be appended to this list + * @return {@code true} (as specified by {@link Collection#add}) + */ + public boolean add(E e) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] elements = getArray(); + int len = elements.length; + Object[] newElements = Arrays.copyOf(elements, len + 1); + newElements[len] = e; + setArray(newElements); + return true; + } finally { + lock.unlock(); + } + } +``` +1. 加锁 +2. 获取元素数组 +3. 新建一个数组,大小为原数组长度加1,并把原数组元素拷贝到新数组 +4. 把新添加的元素放到新数组的末尾 +5. 把新数组赋值给当前对象的array属性,覆盖原数组 +6. 解锁 + +# ConcurrentHashMap +## 各种锁 +### synchronized +java中的关键字,内部实现为监视器锁,主要是通过对象中的字段来表明。 + + + +## 获取元素 +1. hash到元素所在的桶; +2. 如果桶中第一个元素就是该找的元素,直接返回; +3. 如果是树或者正在迁移元素,则调用各自Node子类的find()方法寻找元素; +4. 如果是链表,遍历整个链表寻找元素; +5. 获取元素没有加锁; + +## 删除元素 +1. 计算hash +2. 如果所在的桶不存在,表示没有找到目标元素,返回 +3. 如果正在扩容,则协助扩容完成后再进行删除操作 +4. 如果是以链表形式存储的,则遍历整个链表查找元素,找到之后再删除; +5. 如果是以树形式存储的,则遍历树查找元素,找到之后再删除; +6. 如果是以树形式存储的,删除元素之后树较小,则退化成链表; +7. 如果确实删除了元素,则整个map元素个数减1,并返回旧值; +8. 如果没有删除元素,则返回null; + +### 总结 +1. ConcurrentHashMap是HashMap的线程安全版本; +2. ConcurrentHashMap采用(数组 + 链表 + 红黑树)的结构存储元素; +3. ConcurrentHashMap相比于同样线程安全的HashTable,效率要高很多; +4. ConcurrentHashMap采用的锁有 synchronized,CAS,自旋锁,分段锁,volatile等; +5. ConcurrentHashMap中没有threshold和loadFactor这两个字段,而是采用sizeCtl来控制; + + +# ArrayBlockingQueue + + +# ConcurrentLinkedQueue \ No newline at end of file -- Gitee