jdk/src/share/classes/java/util/concurrent/atomic/LongAdder.java
changeset 15283 e331a847ff27
child 21356 ad2735d41496
equal deleted inserted replaced
15282:4642fe251f37 15283:e331a847ff27
       
     1 /*
       
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     3  *
       
     4  * This code is free software; you can redistribute it and/or modify it
       
     5  * under the terms of the GNU General Public License version 2 only, as
       
     6  * published by the Free Software Foundation.  Oracle designates this
       
     7  * particular file as subject to the "Classpath" exception as provided
       
     8  * by Oracle in the LICENSE file that accompanied this code.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21  * or visit www.oracle.com if you need additional information or have any
       
    22  * questions.
       
    23  */
       
    24 
       
    25 /*
       
    26  * This file is available under and governed by the GNU General Public
       
    27  * License version 2 only, as published by the Free Software Foundation.
       
    28  * However, the following notice accompanied the original version of this
       
    29  * file:
       
    30  *
       
    31  * Written by Doug Lea with assistance from members of JCP JSR-166
       
    32  * Expert Group and released to the public domain, as explained at
       
    33  * http://creativecommons.org/publicdomain/zero/1.0/
       
    34  */
       
    35 
       
    36 package java.util.concurrent.atomic;
       
    37 import java.io.Serializable;
       
    38 
       
    39 /**
       
    40  * One or more variables that together maintain an initially zero
       
    41  * {@code long} sum.  When updates (method {@link #add}) are contended
       
    42  * across threads, the set of variables may grow dynamically to reduce
       
    43  * contention. Method {@link #sum} (or, equivalently, {@link
       
    44  * #longValue}) returns the current total combined across the
       
    45  * variables maintaining the sum.
       
    46  *
       
    47  * <p>This class is usually preferable to {@link AtomicLong} when
       
    48  * multiple threads update a common sum that is used for purposes such
       
    49  * as collecting statistics, not for fine-grained synchronization
       
    50  * control.  Under low update contention, the two classes have similar
       
    51  * characteristics. But under high contention, expected throughput of
       
    52  * this class is significantly higher, at the expense of higher space
       
    53  * consumption.
       
    54  *
       
    55  * <p>LongAdders can be used with a {@link
       
    56  * java.util.concurrent.ConcurrentHashMap} to maintain a scalable
       
    57  * frequency map (a form of histogram or multiset). For example, to
       
    58  * add a count to a {@code ConcurrentHashMap<String,LongAdder> freqs},
       
    59  * initializing if not already present, you can use {@code
       
    60  * freqs.computeIfAbsent(k -> new LongAdder()).increment();}
       
    61  *
       
    62  * <p>This class extends {@link Number}, but does <em>not</em> define
       
    63  * methods such as {@code equals}, {@code hashCode} and {@code
       
    64  * compareTo} because instances are expected to be mutated, and so are
       
    65  * not useful as collection keys.
       
    66  *
       
    67  * @since 1.8
       
    68  * @author Doug Lea
       
    69  */
       
    70 public class LongAdder extends Striped64 implements Serializable {
       
    71     private static final long serialVersionUID = 7249069246863182397L;
       
    72 
       
    73     /**
       
    74      * Creates a new adder with initial sum of zero.
       
    75      */
       
    76     public LongAdder() {
       
    77     }
       
    78 
       
    79     /**
       
    80      * Adds the given value.
       
    81      *
       
    82      * @param x the value to add
       
    83      */
       
    84     public void add(long x) {
       
    85         Cell[] as; long b, v; int m; Cell a;
       
    86         if ((as = cells) != null || !casBase(b = base, b + x)) {
       
    87             boolean uncontended = true;
       
    88             if (as == null || (m = as.length - 1) < 0 ||
       
    89                 (a = as[getProbe() & m]) == null ||
       
    90                 !(uncontended = a.cas(v = a.value, v + x)))
       
    91                 longAccumulate(x, null, uncontended);
       
    92         }
       
    93     }
       
    94 
       
    95     /**
       
    96      * Equivalent to {@code add(1)}.
       
    97      */
       
    98     public void increment() {
       
    99         add(1L);
       
   100     }
       
   101 
       
   102     /**
       
   103      * Equivalent to {@code add(-1)}.
       
   104      */
       
   105     public void decrement() {
       
   106         add(-1L);
       
   107     }
       
   108 
       
   109     /**
       
   110      * Returns the current sum.  The returned value is <em>NOT</em> an
       
   111      * atomic snapshot; invocation in the absence of concurrent
       
   112      * updates returns an accurate result, but concurrent updates that
       
   113      * occur while the sum is being calculated might not be
       
   114      * incorporated.
       
   115      *
       
   116      * @return the sum
       
   117      */
       
   118     public long sum() {
       
   119         Cell[] as = cells; Cell a;
       
   120         long sum = base;
       
   121         if (as != null) {
       
   122             for (int i = 0; i < as.length; ++i) {
       
   123                 if ((a = as[i]) != null)
       
   124                     sum += a.value;
       
   125             }
       
   126         }
       
   127         return sum;
       
   128     }
       
   129 
       
   130     /**
       
   131      * Resets variables maintaining the sum to zero.  This method may
       
   132      * be a useful alternative to creating a new adder, but is only
       
   133      * effective if there are no concurrent updates.  Because this
       
   134      * method is intrinsically racy, it should only be used when it is
       
   135      * known that no threads are concurrently updating.
       
   136      */
       
   137     public void reset() {
       
   138         Cell[] as = cells; Cell a;
       
   139         base = 0L;
       
   140         if (as != null) {
       
   141             for (int i = 0; i < as.length; ++i) {
       
   142                 if ((a = as[i]) != null)
       
   143                     a.value = 0L;
       
   144             }
       
   145         }
       
   146     }
       
   147 
       
   148     /**
       
   149      * Equivalent in effect to {@link #sum} followed by {@link
       
   150      * #reset}. This method may apply for example during quiescent
       
   151      * points between multithreaded computations.  If there are
       
   152      * updates concurrent with this method, the returned value is
       
   153      * <em>not</em> guaranteed to be the final value occurring before
       
   154      * the reset.
       
   155      *
       
   156      * @return the sum
       
   157      */
       
   158     public long sumThenReset() {
       
   159         Cell[] as = cells; Cell a;
       
   160         long sum = base;
       
   161         base = 0L;
       
   162         if (as != null) {
       
   163             for (int i = 0; i < as.length; ++i) {
       
   164                 if ((a = as[i]) != null) {
       
   165                     sum += a.value;
       
   166                     a.value = 0L;
       
   167                 }
       
   168             }
       
   169         }
       
   170         return sum;
       
   171     }
       
   172 
       
   173     /**
       
   174      * Returns the String representation of the {@link #sum}.
       
   175      * @return the String representation of the {@link #sum}
       
   176      */
       
   177     public String toString() {
       
   178         return Long.toString(sum());
       
   179     }
       
   180 
       
   181     /**
       
   182      * Equivalent to {@link #sum}.
       
   183      *
       
   184      * @return the sum
       
   185      */
       
   186     public long longValue() {
       
   187         return sum();
       
   188     }
       
   189 
       
   190     /**
       
   191      * Returns the {@link #sum} as an {@code int} after a narrowing
       
   192      * primitive conversion.
       
   193      */
       
   194     public int intValue() {
       
   195         return (int)sum();
       
   196     }
       
   197 
       
   198     /**
       
   199      * Returns the {@link #sum} as a {@code float}
       
   200      * after a widening primitive conversion.
       
   201      */
       
   202     public float floatValue() {
       
   203         return (float)sum();
       
   204     }
       
   205 
       
   206     /**
       
   207      * Returns the {@link #sum} as a {@code double} after a widening
       
   208      * primitive conversion.
       
   209      */
       
   210     public double doubleValue() {
       
   211         return (double)sum();
       
   212     }
       
   213 
       
   214     private void writeObject(java.io.ObjectOutputStream s)
       
   215         throws java.io.IOException {
       
   216         s.defaultWriteObject();
       
   217         s.writeLong(sum());
       
   218     }
       
   219 
       
   220     private void readObject(java.io.ObjectInputStream s)
       
   221         throws java.io.IOException, ClassNotFoundException {
       
   222         s.defaultReadObject();
       
   223         cellsBusy = 0;
       
   224         cells = null;
       
   225         base = s.readLong();
       
   226     }
       
   227 
       
   228 }