1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 */ 6 7 package java.util.concurrent.atomic; 8 9 import java.io.Serializable; 10 11 /** 12 * One or more variables that together maintain an initially zero 13 * {@code long} sum. When updates (method {@link #add}) are contended 14 * across threads, the set of variables may grow dynamically to reduce 15 * contention. Method {@link #sum} (or, equivalently, {@link 16 * #longValue}) returns the current total combined across the 17 * variables maintaining the sum. 18 * 19 * <p>This class is usually preferable to {@link AtomicLong} when 20 * multiple threads update a common sum that is used for purposes such 21 * as collecting statistics, not for fine-grained synchronization 22 * control. Under low update contention, the two classes have similar 23 * characteristics. But under high contention, expected throughput of 24 * this class is significantly higher, at the expense of higher space 25 * consumption. 26 * 27 * <p>LongAdders can be used with a {@link 28 * java.util.concurrent.ConcurrentHashMap} to maintain a scalable 29 * frequency map (a form of histogram or multiset). For example, to 30 * add a count to a {@code ConcurrentHashMap<String,LongAdder> freqs}, 31 * initializing if not already present, you can use {@code 32 * freqs.computeIfAbsent(key, k -> new LongAdder()).increment();} 33 * 34 * <p>This class extends {@link Number}, but does <em>not</em> define 35 * methods such as {@code equals}, {@code hashCode} and {@code 36 * compareTo} because instances are expected to be mutated, and so are 37 * not useful as collection keys. 38 * 39 * @since 1.8 40 * @author Doug Lea 41 */ 42 public class LongAdder extends Striped64 implements Serializable { 43 private static final long serialVersionUID = 7249069246863182397L; 44 45 /** 46 * Creates a new adder with initial sum of zero. 47 */ LongAdder()48 public LongAdder() { 49 } 50 51 /** 52 * Adds the given value. 53 * 54 * @param x the value to add 55 */ add(long x)56 public void add(long x) { 57 Cell[] as; long b, v; int m; Cell a; 58 if ((as = cells) != null || !casBase(b = base, b + x)) { 59 boolean uncontended = true; 60 if (as == null || (m = as.length - 1) < 0 || 61 (a = as[getProbe() & m]) == null || 62 !(uncontended = a.cas(v = a.value, v + x))) 63 longAccumulate(x, null, uncontended); 64 } 65 } 66 67 /** 68 * Equivalent to {@code add(1)}. 69 */ increment()70 public void increment() { 71 add(1L); 72 } 73 74 /** 75 * Equivalent to {@code add(-1)}. 76 */ decrement()77 public void decrement() { 78 add(-1L); 79 } 80 81 /** 82 * Returns the current sum. The returned value is <em>NOT</em> an 83 * atomic snapshot; invocation in the absence of concurrent 84 * updates returns an accurate result, but concurrent updates that 85 * occur while the sum is being calculated might not be 86 * incorporated. 87 * 88 * @return the sum 89 */ sum()90 public long sum() { 91 Cell[] as = cells; 92 long sum = base; 93 if (as != null) { 94 for (Cell a : as) 95 if (a != null) 96 sum += a.value; 97 } 98 return sum; 99 } 100 101 /** 102 * Resets variables maintaining the sum to zero. This method may 103 * be a useful alternative to creating a new adder, but is only 104 * effective if there are no concurrent updates. Because this 105 * method is intrinsically racy, it should only be used when it is 106 * known that no threads are concurrently updating. 107 */ reset()108 public void reset() { 109 Cell[] as = cells; 110 base = 0L; 111 if (as != null) { 112 for (Cell a : as) 113 if (a != null) 114 a.reset(); 115 } 116 } 117 118 /** 119 * Equivalent in effect to {@link #sum} followed by {@link 120 * #reset}. This method may apply for example during quiescent 121 * points between multithreaded computations. If there are 122 * updates concurrent with this method, the returned value is 123 * <em>not</em> guaranteed to be the final value occurring before 124 * the reset. 125 * 126 * @return the sum 127 */ sumThenReset()128 public long sumThenReset() { 129 Cell[] as = cells; 130 long sum = base; 131 base = 0L; 132 if (as != null) { 133 for (Cell a : as) { 134 if (a != null) { 135 sum += a.value; 136 a.reset(); 137 } 138 } 139 } 140 return sum; 141 } 142 143 /** 144 * Returns the String representation of the {@link #sum}. 145 * @return the String representation of the {@link #sum} 146 */ toString()147 public String toString() { 148 return Long.toString(sum()); 149 } 150 151 /** 152 * Equivalent to {@link #sum}. 153 * 154 * @return the sum 155 */ longValue()156 public long longValue() { 157 return sum(); 158 } 159 160 /** 161 * Returns the {@link #sum} as an {@code int} after a narrowing 162 * primitive conversion. 163 */ intValue()164 public int intValue() { 165 return (int)sum(); 166 } 167 168 /** 169 * Returns the {@link #sum} as a {@code float} 170 * after a widening primitive conversion. 171 */ floatValue()172 public float floatValue() { 173 return (float)sum(); 174 } 175 176 /** 177 * Returns the {@link #sum} as a {@code double} after a widening 178 * primitive conversion. 179 */ doubleValue()180 public double doubleValue() { 181 return (double)sum(); 182 } 183 184 /** 185 * Serialization proxy, used to avoid reference to the non-public 186 * Striped64 superclass in serialized forms. 187 * @serial include 188 */ 189 private static class SerializationProxy implements Serializable { 190 private static final long serialVersionUID = 7249069246863182397L; 191 192 /** 193 * The current value returned by sum(). 194 * @serial 195 */ 196 private final long value; 197 SerializationProxy(LongAdder a)198 SerializationProxy(LongAdder a) { 199 value = a.sum(); 200 } 201 202 /** 203 * Returns a {@code LongAdder} object with initial state 204 * held by this proxy. 205 * 206 * @return a {@code LongAdder} object with initial state 207 * held by this proxy 208 */ readResolve()209 private Object readResolve() { 210 LongAdder a = new LongAdder(); 211 a.base = value; 212 return a; 213 } 214 } 215 216 /** 217 * Returns a 218 * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.LongAdder.SerializationProxy"> 219 * SerializationProxy</a> 220 * representing the state of this instance. 221 * 222 * @return a {@link SerializationProxy} 223 * representing the state of this instance 224 */ writeReplace()225 private Object writeReplace() { 226 return new SerializationProxy(this); 227 } 228 229 /** 230 * @param s the stream 231 * @throws java.io.InvalidObjectException always 232 */ readObject(java.io.ObjectInputStream s)233 private void readObject(java.io.ObjectInputStream s) 234 throws java.io.InvalidObjectException { 235 throw new java.io.InvalidObjectException("Proxy required"); 236 } 237 238 } 239