概念:Compare And Swap/Set,3 个参数 CAS(V,E,N)。V 表示要更新的变量(内存值),E 表示预期值(旧的),N 表示新值。当且仅当 V 值等于 E 值时,才会将 V 的值设为 N,如果 V 值和 E 值不同,则说明已经有其他线程做了更新,则当前线程什么都不做。最后,CAS 返回当前 V 的真实值。
/** * Atomically increments by one the current value. * * @return the previous value */ publicfinalintgetAndIncrement(){ return unsafe.getAndAddInt(this, valueOffset, 1); } }
/** * Atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * * @param expect the expected value * @param update the new value * @return {@code true} if successful. False return indicates that * the actual value was not equal to the expected value. */ publicfinalbooleancompareAndSet(boolean expect, boolean update){ int e = expect ? 1 : 0; int u = update ? 1 : 0; return unsafe.compareAndSwapInt(this, valueOffset, e, u); }
privatestaticclassPair<T> { final T reference; // 维护的版本 finalint stamp; privatePair(T reference, int stamp){ this.reference = reference; this.stamp = stamp; } static <T> Pair<T> of(T reference, int stamp){ returnnew Pair<T>(reference, stamp); } }
privatevolatile Pair<V> pair;
/** * Creates a new {@code AtomicStampedReference} with the given * initial values. * * @param initialRef the initial reference * @param initialStamp the initial stamp */ publicAtomicStampedReference(V initialRef, int initialStamp){ pair = Pair.of(initialRef, initialStamp); }
/** * Atomically sets the value of both the reference and stamp * to the given update values if the * current reference is {@code ==} to the expected reference * and the current stamp is equal to the expected stamp. * * @param expectedReference the expected value of the reference * @param newReference the new value for the reference * @param expectedStamp the expected value of the stamp * @param newStamp the new value for the stamp * @return {@code true} if successful */ publicbooleancompareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp){ Pair<V> current = pair; return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); } }
/** * Creates a new {@code AtomicMarkableReference} with the given * initial values. * * @param initialRef the initial reference * @param initialMark the initial mark */ publicAtomicMarkableReference(V initialRef, boolean initialMark){ pair = Pair.of(initialRef, initialMark); }
/** * Atomically sets the value of both the reference and mark * to the given update values if the * current reference is {@code ==} to the expected reference * and the current mark is equal to the expected mark. * * @param expectedReference the expected value of the reference * @param newReference the new value for the reference * @param expectedMark the expected value of the mark * @param newMark the new value for the mark * @return {@code true} if successful */ publicbooleancompareAndSet(V expectedReference, V newReference, boolean expectedMark, boolean newMark){ Pair<V> current = pair; return expectedReference == current.reference && expectedMark == current.mark && ((newReference == current.reference && newMark == current.mark) || casPair(current, Pair.of(newReference, newMark))); } }
/** Number of CPUS, to place bound on table size */ staticfinalint NCPU = Runtime.getRuntime().availableProcessors();
/** * Table of cells. When non-null, size is a power of 2. */ transientvolatile Cell[] cells;
/** * Base value, used mainly when there is no contention, but also as * a fallback during table initialization races. Updated via CAS. */ transientvolatilelong base;
/** * Spinlock (locked via CAS) used when resizing and/or creating Cells. */ transientvolatileint cellsBusy;
/** * Returns the current sum. The returned value is <em>NOT</em> an * atomic snapshot; invocation in the absence of concurrent * updates returns an accurate result, but concurrent updates that * occur while the sum is being calculated might not be * incorporated. * * @return the sum */ publiclongsum(){ Cell[] as = cells; Cell a; long sum = base; if (as != null) { for (int i = 0; i < as.length; ++i) { if ((a = as[i]) != null) sum += a.value; } } return sum; }