From 5249bfb9462b72bcbba5e680d4be10596f7586a3 Mon Sep 17 00:00:00 2001 From: fyang21117 <1135783636@qq.com> Date: Fri, 20 Dec 2019 11:17:29 +0800 Subject: [PATCH 1/6] add week_01/22/ArrayList.md. --- week_01/22/ArrayList.md | 329 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 week_01/22/ArrayList.md diff --git a/week_01/22/ArrayList.md b/week_01/22/ArrayList.md new file mode 100644 index 0000000..3d166da --- /dev/null +++ b/week_01/22/ArrayList.md @@ -0,0 +1,329 @@ +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.RandomAccess; + +/** + * 【源码链接】 + * Source for java.util.ArrayList: + * http://developer.classpath.org/doc/java/util/ArrayList-source.html + * + * */ + +/** + * 【简介】 + * ArrayList底层使用的是数组来实现List接口,提供了所有可选的List操作并且允许null值。 + * 元素的随机访问是常数时间O(1),在列表中间添加或者删除元素的时间复杂度是O(n)的。 + * 每个List都有一个容量,当达到最大容量时会自动增加自身的容量。 + * 我们可以通过ensureCapacity和trimToSize来确保容量大小,避免重新分配或浪费内存。 + * + * ArrayList不是synchronized的,如果需要多线程访问,可以这样做: + * List list = Collections.synchronizedList(new ArrayList(...)) + * + * 以下就主要方法进行解析说明: + * **/ + + public class ArrayList extends AbstractList implements List,RandomAccess,Cloneable,Serializable{ + + private static final long serialVersionUID = 8683452581122892189L; + + //新建ArrayList的默认容量大小 + private static final int DEFAULT_CAPACITY = 10; + + //ArrayList的元素个数 + private int size; + + //存储数据的数组 + private transient E[] data; + + //根据容量大小来构建ArrayList + public ArrayList(int capacity){ + if(capacity < 0){ + throw new IllegalArgumentException(); + } + data = (E[]) new Object[capacity]; + } + + //默认容量大小来构建ArrayList + public ArrayList(){ + this(DEFAULT_CAPACITY); + } + + //根据给定元素来构建ArrayList + public ArrayList(Collectionc){ + this((int) (c.size() * 1.1f)); + addAll(c); + } + + //修改size使得等于ArrayList实际大小 + public void trimToSize(){ + if(size != data.length){ + E[] newData = (E[]) new Object[size]; + System.arraycopy(data, 0, newData, 0, size); + data = newData; + } + } + + //如果ArrayList容量不足以存储元素,则自动扩展到length*2 + public void ensureCapacity(int minCapacity){ + int current = data.length; + if(minCapacity > current){ + E[] newData = (E[]) new Object[Math.max(current*2, minCapacity)]; + System.arraycopy(data, 0, newData, 0, size); + data = newData; + } + } + + //返回List的元素个数 + public int size(){ + return size; + } + + //判断List是否为空 + public boolean isEmpty(){ + return size == 0; + } + + //判断element是否在ArrayList中 + public boolean contains(Object e){ + return indexOf(e) != -1; + } + + //判断element在ArrayList中首次出现的最低位置索引,否则返回-1 + public int indexOf(Object e){ + for(int i = 0; i < size; i++){ + if(e.equals(data[i])){ + return i; + } + } + return -1; + } + + //判断element在ArrayList中首次出现的最高位置索引,否则返回-1 + public int lastIndexOf(Object e){ + for(int i = size-1; i > 0; i--){ + if(e.equals(data[i])){ + return i; + } + } + return -1; + } + + //ArrayList的浅拷贝 + public Object clone(){ + ArrayList clone = null; + try{ + clone = (ArrayList) super.clone(); + clone.data = (E[]) data.clone(); + }catch(CloneNotSupportedException e){ + + } + return clone; + } + + //返回一个独立的数组,存储ArrayList的所有元素 + public Object[] toArray(){ + E[] array = (E[]) new Object[size]; + System.arraycopy(data, 0, array, 0, size); + return array; + } + + //返回一个运行时传入数组类型的独立数组,存储ArrayList的所有元素 + //如果存储数组的size太小,则扩展为目标类型T的大小 + public T[] toArray(T[] a){ + if(a.length < size){ + a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); + }else if(a.length > size){ + a[size] = null; + } + System.arraycopy(data, 0, a, 0, size); + return a; + } + + //检查索引是否在可能的元素范围内 + private void checkBoundInclusive(int index) { + if(index > size){ + throw new IndexOutOfBoundsException("Index:" + index + ",Size:" + size ); + } + } + + //检查索引是否在现有元素的范围内。 + private void checkBoundExclusive(int index) { + if(index >= size){ + throw new IndexOutOfBoundsException("Index:" + index + ",Size:" + size ); + } + } + + //检索用户提供的索引处的元素 + public E get(int index){ + checkBoundExclusive(index); + return data[index]; + } + + //给特定下标元素进行赋值,返回以前位于指定索引处的元素 + public E set(int index, E e){ + checkBoundExclusive(index); + E result = data[index]; + data[index] = e; + return result; + } + + //在ArrayList的尾部添加元素:如果已满,则size+1; + //modCount字段表示list结构上被修改的次数. + public boolean add(E e){ + modCount++; + if(size == data.length){ + ensureCapacity(size + 1); + } + data[size++] = e; + return true; + } + + //根据索引下标位置添加元素:如果已满,则size+1; + //如果插入位置不是尾部,将index后面元素往后移动一位,再插入元素于index + public void add(int index , Collection c) { + checkBoundExclusive(index); + modCount++; + if (size == data.length) { + ensureCapacity(size + 1); + } + if (index != size) { + System.arraycopy(data, index, data, index + 1, size - index); + } + data[index] = c; + size++; + } + + //根据索引下标位置移除元素 + public E remove(int index){ + checkBoundExclusive(index); + E r = data[index]; + modCount++; + if(index != --size){ + System.arraycopy(data, index, data, index + 1, size - index); + } + data[size] = null; + return r; + } + + //清空ArrayList + public void clear(){ + if(size > 0 ){ + modCount++; + Arrays.fill(data, 0, size, null); + size = 0 ; + } + } + + //将提供的集合中的每个元素添加到此列表 + public boolean addAll(Collectionc){ + return addAll(size, c); + } + + //将提供的集合中的每个元素添加到此列表index开始的位置:先将index后面元素移动csize个位置,然后插入 + public boolean addAll(int index,Collectionc){ + checkBoundExclusive(index); + Iterator itr = c.iterator(); + int csize = c.size(); + + modCount++; + if(csize+size > data.length){ + ensureCapacity(size + csize); + } + //移动原列表元素 + int end = index + csize; + if(size > 0 && index != size){ + System.arraycopy(data, index, data, end, size - index); + } + size += csize; + //添加新元素 + for(;index < end;index++){ + data[index] = itr.next(); + } + return csize>0; + } + + //移除在某个范围间隔的列表元素:将toIndex后面的元素往前移动(size - toIndex)位 + protected void removeRange(int fromIndex, int toIndex){ + int change = toIndex - fromIndex; + if(change > 0){ + modCount++; + System.arraycopy(data, toIndex, data, fromIndex, size - toIndex); + size -= change; + } + else if(change < 0){ + throw new IndexOutOfBoundsException(); + } + } + + //从此列表中删除给定集合中包含的所有元素 + //判断元素存在,如【a,b,c,d】中存在【b】,返回下标i=1,将【c,d】前移获得【a,c,d】 + boolean removeAllInternal(Collectionc){ + int i,j; + for(i=0;ic){ + int i,j; + for(i=0;i Date: Fri, 20 Dec 2019 11:19:37 +0800 Subject: [PATCH 2/6] add week_01/22/LinkedList.md. --- week_01/22/LinkedList.md | 699 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 699 insertions(+) create mode 100644 week_01/22/LinkedList.md diff --git a/week_01/22/LinkedList.md b/week_01/22/LinkedList.md new file mode 100644 index 0000000..eaf11e7 --- /dev/null +++ b/week_01/22/LinkedList.md @@ -0,0 +1,699 @@ + +import java.io.IOError; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.AbstractSequentialList; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Deque; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; + + +/** + * 【源码链接】 + * Source for java.util.ArrayList: + * http://developer.classpath.org/doc/java/util/LinkedList-source.html + * + * */ + + /** + * 【简介】 + * LinkedList实现了List接口,除了List相关方法外,该类还提供了在O(1)时间内访问第一个和最后一个List元素的权限, + * 以便轻松创建堆栈、队列或双端队列(deque)。LinkedList是双向链表的,从最靠近元素的一端开始遍历给定的索引。 + * + * LinkedList不是线程同步的(non-synchronized),如果需要多线程访问可以这样做: + * List list = Collections.synchronizedList(new LinkedList(...)) + * + * LinkedList在队列首尾添加、删除元素的时间复杂度为O(1),中间添加、删除为O(n),不支持随机访问。 + * */ + + public class LinkedList extends AbstractSequentialList implements List,Deque,Cloneable,Serializable{ + + private static final long serialVersionUID = 876323262645176354L; + + //LinkedList第一个元素 + transient Entry first; + + //LinkedList最后一个元素 + transient Entry last; + + //LinkedList的长度 + transient int size = 0; + + //新建内部类来表示列表中的项,包含单个元素。 + private static final class Entry{ + //列表元素 + T data; + //后继指针 + Entry next; + //前继指针 + Entry previous; + + Entry(T data){ + this.data = data; + } + } + + //获取LinkedList位置下标为n的元素,顺序or倒序 + Entry getEntry(int n){ + Entry e; + if(n < size/2){ + e = first; + while(n-- > 0){ + e = e.next; + } + }else{ + e = last; + while(++n < size){ + e = e.previous; + } + } + return e; + } + + //从列表中删除条目。这将调整大小并适当处理“first”和“last” + //modCount字段表示list结构上被修改的次数. + void removeEntry(Entry e){ + modCount++; + size--; + if(size == 0){ + first = last = null; + }else { + if(e == first){ + first = e.next; + e.next.previous = null; + }else if(e == last){ + last = e.previous; + e.previous.next = null; + }else{ + e.next.previous = e.previous; + e.previous.next = e.next; + } + } + } + + //检查索引是否在可能的元素范围内 + private void checkBoundsInclusive(int index){ + if(index < 0 || index > size){ + throw new IndexOutOfBoundsException("Index:"+index+",Size:"+size); + } + } + + //检查索引是否在现有元素的范围内。 + private void checkBoundsExclusive(int index){ + if(index < 0 || index >= size){ + throw new IndexOutOfBoundsException("Index:"+index+",Size:"+size); + } + } + + //创建一个空的LinkedList + public LinkedList(){ + + } + + //根据给定元素创建一个LinkedList + public LinkedList(Collection c){ + addAll(c); + } + + //返回LinkedList第一个元素 + public T getFirst(){ + if(size ==0){ + throw new NoSuchElementException(); + } + return first.data; + } + + //返回LinkedList最后一个元素 + public T getLast(){ + if(size == 0){ + throw new NoSuchElementException(); + } + return last.data; + } + + //移除并返回LinkedList第一个元素 + public T removeFirst(){ + if(size == 0){ + throw new NoSuchElementException(); + } + modCount++; + size--; + T r = first.data; + + if(first.next != null){ + first.next.previous = null; + }else{ + last = null; + } + + first = first.next; + return r; + } + + //移除并返回LinkedList最后一个元素 + public T removeLast(){ + if(size == 0){ + throw new NoSuchElementException(); + } + modCount++; + size--; + T r = last.data; + + if(last.previous != null){ + last.previous.next = null; + }else{ + first = null; + } + + last = last.previous; + return r; + } + + //在LinkedList首部插入元素 + public void addFirst(T o){ + Entry e = new Entry<>(o); + modCount++; + if(size == 0){ + first = last = e; + }else{ + e.next = first; + first.previous = e; + first = e; + } + size++; + } + + //在LinkedList尾部插入元素 + public void addLast(T o){ + addLastEntry(new Entry(o)); + } + private void addLastEntry(Entry e) { + modCount++; + if(size ==0){ + first = last = e; + }else{ + e.previous = last; + last.next = e; + last = e; + } + size++; + } + + //如果列表包含给定的对象,则返回true + public boolean contains(Object o){ + Entry e = first; + while(e != null){ + if(o.equals(e.data)){ + return true; + } + e = e.next; + } + return false; + } + + //返回LinkedList的大小 + public int size(){ + return size; + } + + //在LinkedList尾部添加元素 + public boolean add(T o){ + addLastEntry(new Entry(o)); + return true; + } + + //删除列表中与给定对象匹配的最低索引处的项 + public boolean remove(Object o){ + Entry e = first; + while(e != null){ + if(o.equals(e.data)){ + removeEntry(e); + return true; + } + e = e.next; + } + return false; + } + + //按迭代顺序将集合的元素追加到此列表的末尾 + public boolean addAll(Collection c){ + return addAll(size,c); + } + + //在此列表的给定索引处按迭代顺序插入集合的元素 + public boolean addAll(int index,Collection c){ + checkBoundsInclusive(index); + int csize = c.size(); + if(csize == 0){ + return false; + } + Iterator itr = c.iterator(); + + Entry after = null; + Entry before = null; + if(index != size){ + after = getEntry(index); + before = after.previous; + }else{ + before = last; + } + + //创建第一个新条目。我们还没有设置从“before”到第一个条目的链接, + Entry e = new Entry(itr.next()); + e.previous = before; + Entry prev = e; + Entry firstNew = e; + + //创建并链接所有剩余条目。 + for(int pos = 1;pos < csize; pos++){ + e = new Entry(itr.next()); + e.previous = prev; + prev.next = e; + prev = e; + } + + //将新的条目链链接到列表中。 + modCount++; + size += csize; + prev.next = after; + if(after != null){ + after.previous = e; + }else{ + last = e; + } + if(before != null){ + before.next = firstNew; + }else{ + first = firstNew; + } + return true; + } + + //清空LinkedList + public void clear(){ + if(size > 0 ){ + modCount++; + first = null; + last = null; + size =0; + } + } + + //获取元素的下标 + public T get(int index){ + checkBoundsExclusive(index); + return getEntry(index).data; + } + + //替换列表中给定位置的元素。 + public T set(int index,T o){ + checkBoundsExclusive(index); + Entry e = getEntry(index); + T old = e.data; + e.data = o; + return old; + } + + //在列表中d 给定位置插入元素。 + public void add(int index ,T o){ + checkBoundsInclusive(index); + Entry e = new Entry(o); + if(index after = getEntry(index); + e.next = after; + e.previous = after.previous; + if(after.previous == null){ + first = e; + }else{ + after.previous.next = e; + } + after.previous = e; + size ++; + }else{ + addLastEntry(e); + } + } + + //从列表中删除位于给定位置的元素。 + public T remove(int index){ + checkBoundsExclusive(index); + Entry e = getEntry(index); + removeEntry(e); + return e.data; + } + + //返回元素位于列表中的第一个索引,或-1 + public int indexOf(Object o){ + int index = 0; + Entry e = first; + while(e != null){ + if(o.equals(e.data)){ + return index; + } + index ++; + e = e.next; + } + return -1; + } + + //返回元素位于列表中的最后一个索引,或-1。 + public int lastIndexOf(Object o){ + int index = size -1; + Entry e = last; + while(e != null){ + if(o.equals(e.data)){ + return index; + } + index --; + e = e.previous; + } + return -1; + } + + //从给定的索引开始,获取此列表上的ListIterator。此方法返回的ListIterator支持add、remove和set方法。 + public ListIterator listIterator(int index){ + checkBoundsInclusive(index); + return new LinkedListItr(index); + } + //列表上的列表迭代器。这个类跟踪它在列表中的位置以及它所处的两个列表项。 + private final class LinkedListItr implements ListIterator{ + + private int konwnMod = modCount; + private Entry next; + private Entry previous; + private Entry lastReturned; + private int position; + + //初始化迭代器 + public LinkedListItr(int index) { + if(index == size){ + next = null; + previous = (Entry) last; + }else{ + next = (Entry)getEntry(index); + previous = next.previous; + } + position = index; + } + + //检查迭代器的一致性。 + private void checkMod(){ + if(konwnMod != modCount) + throw new ConcurrentModificationException(); + } + + //返回下一个元素的下标 + public int nextIndex(){ + return position; + } + + //返回前一个元素的下标 + public int previousIndex(){ + return position-1; + } + + //如果通过下一个元素存在更多元素,则返回true。 + public boolean hasNext(){ + return (next != null); + } + + //如果先前存在更多元素,则返回true。 + public boolean hasPrevious(){ + return (previous != null); + } + + //返回下一个元素 + public I next(){ + checkMod(); + if(next == null) + throw new NoSuchElementException(); + position++; + lastReturned = previous = next; + next = lastReturned.next; + return lastReturned.data; + } + + //返回前一个元素 + public I previous(){ + checkMod(); + if(previous == null) + throw new NoSuchElementException(); + position--; + lastReturned = next = previous; + previous = lastReturned.previous; + return lastReturned.data; + } + + //从列表中删除最近返回的元素 + public void remove(){ + checkMod(); + if(lastReturned == null){ + throw new IllegalStateException(); + } + if(lastReturned == previous){ + position--; + } + + next = lastReturned.next; + previous = lastReturned.previous; + removeEntry((Entry)lastReturned); + + konwnMod++; + lastReturned = null; + } + + //在上一个和下一个之间添加元素,然后前进到下一个。 + public void add(I o){ + checkMod(); + modCount++; + konwnMod++; + size++; + position++; + Entry e = new Entry(o); + e.previous = previous; + e.next = next; + + if(previous != null) + previous.next = e; + else + first = (Entry)e; + + if(next != null){ + next.previous = e; + }else{ + last = (Entry) e; + } + previous = e; + lastReturned = null; + } + + //更改最近返回的元素的内容。 + public void set(I o){ + checkMod(); + if(lastReturned == null){ + throw new IllegalStateException(); + } + lastReturned.data = o; + } + } + + + + //LinkedList的浅拷贝 + public Object clone(){ + LinkedList copy = null; + try{ + copy = (LinkedList) super.clone(); + }catch(CloneNotSupportedException ex){ + + } + copy.clear(); + copy.addAll(this); + return copy; + } + + //返回按顺序包含列表元素的数组。 + public Object[] toArray(){ + Object[] array = new Object[size]; + Entry e = first; + for(int i=0;i S[] toArray(S[] a){ + if(a.length < size){ + a = (S[])Array.newInstance(a.getClass().getComponentType(), size); + }else if(a.length > size){ + a[size] = null; + } + Entry e = first; + for(int i=0;i e = first; + while(e != null){ + s.writeObject(e.data); + e = e.next; + } + } + + //从给定流反序列化此对象。 + private void readObject(ObjectInputStream s) throws IOException,ClassNotFoundException{ + s.defaultReadObject(); + int i = s.readInt(); + while(--i >= 0){ + addLastEntry(new Entry((T) s.readObject())); + } + } + + //按相反的顺序获取此列表上的迭代器。 + public Iterator descendIterator(){ + return new Iterator() { + private int konwnMod = modCount; + private Entry next =last; + private Entry lastReturned; + private int position = size() - 1; + //检查迭代过程中从其他地方对列表所做的修改。 + private void checkMod(){ + if(konwnMod != modCount) + throw new ConcurrentModificationException(); + } + public boolean hasNext(){ + return next != null; + } + public T next(){ + checkMod(); + if(next == null) + throw new NoSuchElementException(); + --position; + lastReturned = next; + next = lastReturned.previous; + return lastReturned.data; + } + public void remove(){ + checkMod(); + if(lastReturned == null) + throw new IllegalStateException(); + removeEntry(lastReturned); + lastReturned = null; + ++konwnMod; + } + }; + } + + //在列表的前面插入指定的元素。 + public boolean offerFirst(T value){ + addFirst(value); + return true; + } + + //在列表的后面插入指定的元素。 + public boolean offerLast(T value){ + return add(value); + } + + //返回列表的第一个元素而不删除 + public T peekFirst(){ + return peek(); + } + + //返回列表的最后一个元素而不删除 + public T peekLast(){ + if(size == 0){ + return null; + } + return getLast(); + } + + //删除并返回列表的第一个元素 + public T pollFirst(){ + return poll(); + } + + //删除并返回列表的最后一个元素 + public T pollLast(){ + if(size == 0){ + return null; + } + return removeLast(); + } + + //通过移除并返回列表中的第一个元素,从堆栈中弹出一个元素。 + public T pop(){ + return removeFirst(); + } + + //通过将元素添加到列表的前面,将其推送到堆栈上。 + public void push(T value) { + addFirst(value); + } + + //从头到尾遍历列表时,从列表中删除指定元素的第一个匹配项。 + public boolean removeFirstOccurrence(Object o){ + return remove(o); + } + + //从头到尾遍历列表时,从列表中删除指定元素的最后一个匹配项。 + public boolean removeLastOccurrence(Object o){ + Entry e = last; + while(e!=null){ + if(o.equals(e.data)){ + removeEntry(e); + return true; + } + e = e.previous; + } + return false; + } + } \ No newline at end of file -- Gitee From acc2575560074dfc74527eff75ffe08a516204d0 Mon Sep 17 00:00:00 2001 From: fyang21117 <1135783636@qq.com> Date: Fri, 20 Dec 2019 11:21:53 +0800 Subject: [PATCH 3/6] add week_02/22/AtomicStampedReference.md. --- week_02/22/AtomicStampedReference.md | 133 +++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 week_02/22/AtomicStampedReference.md diff --git a/week_02/22/AtomicStampedReference.md b/week_02/22/AtomicStampedReference.md new file mode 100644 index 0000000..178ff4a --- /dev/null +++ b/week_02/22/AtomicStampedReference.md @@ -0,0 +1,133 @@ +/** + * 【源码链接】 + * package java.util.concurrent.atomic; + * 源码链接: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicStampedReference.html + * 参考死磕 java并发包之AtomicStampedReference源码分析(ABA问题详解)链接:https://www.cnblogs.com/tong-yuan/archive/2019/05/09/AtomicStampedReference.html + * + * */ + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; + +public class AtomicStampedReference { + + //内部pair类,存储stamp和reference + private static class Pair { + final T reference; + final int stamp; + private Pair(T reference, int stamp) { + this.reference = reference; + this.stamp = stamp; + } + static Pair of(T reference, int stamp) { + return new Pair(reference, stamp); + } + } + + //声明一个Pair类型的变量。 + private volatile Pair pair; + + /** + * 使用给定的初始值创建新的AtomicStampedReference。 + */ + public AtomicStampedReference(V initialRef, int initialStamp) { + pair = Pair.of(initialRef, initialStamp); + } + + /** + * 返回引用的当前值。 + */ + public V getReference() { + return pair.reference; + } + + /** + * 返回戳记的当前值。 + */ + public int getStamp() { + return pair.stamp; + } + + /** + * 返回引用和戳记的当前值。 + */ + public V get(int[] stampHolder) { + Pair pair = this.pair; + stampHolder[0] = pair.stamp; + return pair.reference; + } + + /** + * 如果当前引用是预期引用,并且当前标记等于预期戳记,则原子地将引用和戳记的值设置为给定的更新值。 + */ + public boolean weakCompareAndSet(V expectedReference, + V newReference, + int expectedStamp, + int newStamp) { + return compareAndSet(expectedReference, newReference, + expectedStamp, newStamp); + } + + /** + * 如果当前引用是预期引用,并且当前戳记等于预期戳记,则原子地将引用和戳记的值设置为给定的更新值。 + * ABA的解决方法: + * 首先,使用版本号控制; + * 其次,不重复使用节点(Pair)的引用,每次都新建一个新的Pair来作为CAS比较的对象,而不是复用旧的; + * 最后,外部传入元素值及版本号,而不是节点(Pair)的引用。 + */ + public boolean compareAndSet(V expectedReference, + V newReference, + int expectedStamp, + int newStamp) { + // 获取当前的(元素值,版本号)对 + Pair current = pair; + return + // 引用没变 + expectedReference == current.reference && + // 版本号没变 + expectedStamp == current.stamp && + // 新引用等于旧引用 + ((newReference == current.reference && + // 新版本号等于旧版本号 + newStamp == current.stamp) || + // 构造新的Pair对象并CAS更新 + casPair(current, Pair.of(newReference, newStamp))); + } + + /** + * 无条件地设置引用和戳记的值。 + */ + public void set(V newReference, int newStamp) { + Pair current = pair; + if (newReference != current.reference || newStamp != current.stamp) + this.pair = Pair.of(newReference, newStamp); + } + + /** + * 如果当前引用是预期引用,则原子性地将戳记的值设置为给定的更新值。 + * 对该操作的任何给定调用可能会错误地失败,但如果当前值保留预期值,并且没有其他线程也试图设置该值,则重复调用将最终成功。 + */ + public boolean attemptStamp(V expectedReference, int newStamp) { + Pair current = pair; + return + expectedReference == current.reference && + (newStamp == current.stamp || + casPair(current, Pair.of(expectedReference, newStamp))); + } + + // VarHandle mechanics + private static final VarHandle PAIR; + static { + try { + MethodHandles.Lookup l = MethodHandles.lookup(); + PAIR = l.findVarHandle(AtomicStampedReference.class, "pair", + Pair.class); + } catch (ReflectiveOperationException e) { + throw new Error(e); + } + } + + private boolean casPair(Pair cmp, Pair val) { + return PAIR.compareAndSet(this, cmp, val); + } +} -- Gitee From 9e5805362ea03383b15b5bb42cab731274dea5c5 Mon Sep 17 00:00:00 2001 From: fyang21117 <1135783636@qq.com> Date: Fri, 20 Dec 2019 11:22:50 +0800 Subject: [PATCH 4/6] add week_02/22/AtomicInteger.md. --- week_02/22/AtomicInteger.md | 189 ++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 week_02/22/AtomicInteger.md diff --git a/week_02/22/AtomicInteger.md b/week_02/22/AtomicInteger.md new file mode 100644 index 0000000..75609a5 --- /dev/null +++ b/week_02/22/AtomicInteger.md @@ -0,0 +1,189 @@ +/** + * 【源码链接】 + * package java.util.concurrent.atomic; + * 源码链接: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html#AtomicInteger() + * 解析1:https://www.cnblogs.com/rever/p/8215743.html + * + * */ + + /** + * 【关于Unsafe】 + * sun.misc.Unsafe是JDK内部用的工具类。它通过暴露一些Java意义上说“不安全”的功能给Java层代码, + * 来让JDK能够更多的使用Java代码来实现一些原本是平台相关的、需要使用native语言(例如C或C++)才可以实现的功能。 + * 该类不应该在JDK核心类库之外使用。 + * + * 【关于AtomicInteger】 + * AtomicInteger中主要实现了整型的原子操作,防止并发情况下出现异常结果,其内部主要依靠JDK中的Unsafe类操作内存中的数据来实现的。 + * volatile修饰符保证了value在内存中其他线程可以看到该值的改变。CAS操作保证了AtomicInteger安全修改value的值。 + * + * AtomicInteger用于原子递增计数器等应用程序中,不能用作整数的替换。但是,这个类确实扩展了Number,允许处理基于数字的类的工具和实用程序进行统一访问。 + * */ +import sun.misc.Unsafe; + +public class AtomicInteger extends Number implements java.io.Serializable { + private static final long serialVersionUID = 6214790243416807050L; + + // setup to use Unsafe.compareAndSwapInt for updates + // Unsafe是JDK内部的工具类,主要实现了平台相关的操作 + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + //valueOffset内存偏移量。AtomicInteger的原子操作都靠内存偏移量来实现的。 + private static final long valueOffset; + + static { + try { + valueOffset = unsafe.objectFieldOffset + (AtomicInteger.class.getDeclaredField("value")); + } catch (Exception ex) { throw new Error(ex); } + } + +/** + * Java存储模型不会对volatile指令的操作进行重排序:保证了对volatile变量的操作按照指令的出现顺序执行的。 + * volatile变量不会被缓存在寄存器中(只有拥有线程可见)或其他CPU不可见的地方,每次都从主存中读取volatile变量的结果。 + * 对一个volatile变量的修改后,其他线程都可以读到此操作的结果(即修改后的值) + * + */ + private volatile int value; + + //使用给定的初始值创建新的AtomicInteger。 + public AtomicInteger(int initialValue) { + value = initialValue; + } + + //创建初始值为0的新AtomicInteger。 + public AtomicInteger() { + } + + //获取当前值. + public final int get() { + return value; + } + + //设置为给定值. + public final void set(int newValue) { + value = newValue; + } + + //最终设置为给定值。 + public final void lazySet(int newValue) { + unsafe.putOrderedInt(this, valueOffset, newValue); + } + + //原子地设置为给定值并返回旧值。 + public final int getAndSet(int newValue) { + for (;;) { + int current = get(); + if (compareAndSet(current, newValue)) + return current; + } + } + +/** + * @param expect + * @param update + * @return + * 这里简单说明一下独占锁和乐观锁的概念: + * 独占锁就是线程获取锁后,其他的线程都需要挂起,直到持有独占锁的线程释放锁; + * 乐观锁就是先假定没有冲突直接进行操作,如果有冲突而失败就重试,直到成功.(CAS机制,compare and swap) + * + * AtomicInteger中的CAS操作就是compareAndSet(),作用是每次从内存中根据内存偏移量(valueOffset)取出数据 + * 将取出的值跟expect比较,如果数据一致就把内存中的值改为update。(这样使用CAS就保证了原子操作) + * + * 更多:对比synchronized实现原子操作,Java中的synchronized锁是独占锁,并发性能差。 + */ + public final boolean compareAndSet(int expect, int update) { + return unsafe.compareAndSwapInt(this, valueOffset, expect, update); + } + + //如果当前值=预期值,原子地将该值设置为给定的更新值。 + //可能会错误地失败,并且不提供排序保证,因此很少是compareAndSet的合适替代方案。 + public final boolean weakCompareAndSet(int expect, int update) { + return unsafe.compareAndSwapInt(this, valueOffset, expect, update); + } + + //原子性地将当前值增加一。 + public final int getAndIncrement() { + for (;;) { + int current = get(); + int next = current + 1; + if (compareAndSet(current, next)) + return current; + } + } + + //原子性地将当前值减少一。 + public final int getAndDecrement() { + for (;;) { + int current = get(); + int next = current - 1; + if (compareAndSet(current, next)) + return current; + } + } + + //原子性地将给定值添加到当前值。 getAndAdd() 相当于 i+=n + public final int getAndAdd(int delta) { + for (;;) { + int current = get(); + int next = current + delta; + if (compareAndSet(current, next)) + return current; + } + } + + //原子性地将当前值增加一。incrementAndGet() 相当于 i++ + public final int incrementAndGet() { + for (;;) { + int current = get(); + int next = current + 1; + if (compareAndSet(current, next)) + return next; + } + } + + //原子性地将当前值减少一。decrementAndGet() 相当于 i-- + public final int decrementAndGet() { + for (;;) { + int current = get(); + int next = current - 1; + if (compareAndSet(current, next)) + return next; + } + } + + //原子地将给定值添加到当前值。 + public final int addAndGet(int delta) { + for (;;) { + int current = get(); + int next = current + delta; + if (compareAndSet(current, next)) + return next; + } + } + + //返回当前值的字符串表示形式。 + public String toString() { + return Integer.toString(get()); + } + + //以整数形式返回指定数字的值。这可能涉及舍入或截断。 + public int intValue() { + return get(); + } + + //将指定数字的值返回为long。这可能涉及舍入或截断。 + public long longValue() { + return (long)get(); + } + + //将指定数字的值返回为float。这可能涉及舍入或截断。 + public float floatValue() { + return (float)get(); + } + + //将指定数字的值返回为double。这可能涉及舍入或截断。 + public double doubleValue() { + return (double)get(); + } + +} \ No newline at end of file -- Gitee From acc2f751f08307a8e7eb7cd560cea8285280895e Mon Sep 17 00:00:00 2001 From: fyang21117 <1135783636@qq.com> Date: Fri, 20 Dec 2019 14:23:35 +0800 Subject: [PATCH 5/6] add week_02/22/LongAdder.md. --- week_02/22/LongAdder.md | 184 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 week_02/22/LongAdder.md diff --git a/week_02/22/LongAdder.md b/week_02/22/LongAdder.md new file mode 100644 index 0000000..06b2ce7 --- /dev/null +++ b/week_02/22/LongAdder.md @@ -0,0 +1,184 @@ + +/** + * 【源码链接】 + * package java.util.concurrent.atomic; + * 源码链接: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/LongAdder.html + * + * + * LongAdder是用于多线程环境下Long类型累加计算的工具类,LongAdder继承自Striped64类,该类实现了主要的功能逻辑. + * + * LongAdder类与AtomicLong类的区别在于 + * (1)高并发时前者将对单一变量的CAS操作分散为对数组cells中多个元素的CAS操作,取值时进行求和; + * (2)而在并发较低时仅对base变量进行CAS操作,与AtomicLong类原理相同。 + * */ + +import java.io.Serializable; +import java.util.concurrent.atomic.AtomicLong; + + +/** + *一个或多个变量一起保持初始零和。 + 当更新跨线程争用时,变量集可能会动态增长以减少争用。等效地,返回保持和的变量。 + * + * 这个类通常用于多个线程更新用于收集统计数据,而不是用于同步控制。在低更新调用的情况下,这两个类具有相似的特性。但在高争用下,该类的预期吞吐量会显著提高,但会牺牲更高的空间消耗。 + */ +public class LongAdder extends Striped64 implements Serializable { + private static final long serialVersionUID = 7249069246863182397L; + + /** + * 创建初始和为零的新加法器。 + */ + public LongAdder() { + } + + /** + * 添加给定值。 + * 这里的类Cell,是Striped64类的静态内部类,因此当Striped64对象初始化时并不会连带将Cell类初始化 + */ + public void add(long x) { + Cell[] cs; long b, v; int m; Cell c; + if ((cs = cells) != null || !casBase(b = base, b + x)) { + boolean uncontended = true; + if (cs == null || (m = cs.length - 1) < 0 || + (c = cs[getProbe() & m]) == null || + !(uncontended = c.cas(v = c.value, v + x))) + longAccumulate(x, null, uncontended); + } + } + + /** + * 自动增加long型数值1,相当于i++ + */ + public void increment() { + add(1L); + } + + /** + * 自动减小long型数值1,相当于i-- + */ + public void decrement() { + add(-1L); + } + + /** + * 返回当前和。 + * 返回的值不是原子快照;在没有并发更新的情况下调用将返回准确的结果, + * 但是在计算总和时发生的并发更新可能不会合并。 + */ + public long sum() { + Cell[] cs = cells; + long sum = base; + if (cs != null) { + for (Cell c : cs) + if (c != null) + sum += c.value; + } + return sum; + } + + /** + * 重置将总和保持为零的变量。 + * 此方法可能是创建新加法器的有用替代方法,但仅在没有并发更新时有效。 + * 因为这个方法本质上是乐观的,所以只有在知道没有线程并发更新时才应该使用它。 + */ + public void reset() { + Cell[] cs = cells; + base = 0L; + if (cs != null) { + for (Cell c : cs) + if (c != null) + c.reset(); + } + } + + /** + * 与sum()后跟reset()等效。 + */ + public long sumThenReset() { + Cell[] cs = cells; + long sum = getAndSetBase(0L); + if (cs != null) { + for (Cell c : cs) { + if (c != null) + sum += c.getAndSet(0L); + } + } + return sum; + } + + /** + * 返回当前值的字符串表示形式。 + */ + public String toString() { + return Long.toString(sum()); + } + + /** + * 以long型返回当前和 + */ + public long longValue() { + return sum(); + } + + /** + * 以int型返回当前和 + */ + public int intValue() { + return (int)sum(); + } + + /** + * 在扩大基本类型转换后,返回float类型sum值 + */ + public float floatValue() { + return (float)sum(); + } + + /** + * 在扩大基本类型转换后,返回double类型sum值 + */ + public double doubleValue() { + return (double)sum(); + } + + /** + * 序列化代理,用于避免引用序列化窗体中的非公共Striped64父类。 + */ + private static class SerializationProxy implements Serializable { + private static final long serialVersionUID = 7249069246863182397L; + + /** + * 当前sum值 + */ + private final long value; + + SerializationProxy(LongAdder a) { + value = a.sum(); + } + + /** + * 返回一个初始状态由该代理持有的对象。 + */ + private Object readResolve() { + LongAdder a = new LongAdder(); + a.base = value; + return a; + } + } + + /** + * + *返回一个序列化代理表示此实例的状态。 + */ + private Object writeReplace() { + return new SerializationProxy(this); + } + + + private void readObject(java.io.ObjectInputStream s) + throws java.io.InvalidObjectException { + throw new java.io.InvalidObjectException("Proxy required"); + } + +} + -- Gitee From 5d15616c26961365be978945ac122a16dff5b13c Mon Sep 17 00:00:00 2001 From: fyang21117 <1135783636@qq.com> Date: Fri, 20 Dec 2019 14:24:27 +0800 Subject: [PATCH 6/6] update week_02/22/LongAdder.md. --- week_02/22/LongAdder.md | 1 + 1 file changed, 1 insertion(+) diff --git a/week_02/22/LongAdder.md b/week_02/22/LongAdder.md index 06b2ce7..43f7508 100644 --- a/week_02/22/LongAdder.md +++ b/week_02/22/LongAdder.md @@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicLong; * * 这个类通常用于多个线程更新用于收集统计数据,而不是用于同步控制。在低更新调用的情况下,这两个类具有相似的特性。但在高争用下,该类的预期吞吐量会显著提高,但会牺牲更高的空间消耗。 */ + public class LongAdder extends Striped64 implements Serializable { private static final long serialVersionUID = 7249069246863182397L; -- Gitee