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