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