ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/atomic/LongAdder.java
Revision: 1.23
Committed: Fri Nov 27 17:43:34 2020 UTC (3 years, 6 months ago) by dl
Branch: MAIN
CVS Tags: HEAD
Changes since 1.22: +3 -2 lines
Log Message:
Incorporate snippets code improvements from Pavel Rappo

File Contents

# Content
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 */
48 public LongAdder() {
49 }
50
51 /**
52 * Adds the given value.
53 *
54 * @param x the value to add
55 */
56 public void add(long x) {
57 Cell[] cs; long b, v; int m; Cell c;
58 if ((cs = cells) != null || !casBase(b = base, b + x)) {
59 int index = getProbe();
60 boolean uncontended = true;
61 if (cs == null || (m = cs.length - 1) < 0 ||
62 (c = cs[index & m]) == null ||
63 !(uncontended = c.cas(v = c.value, v + x)))
64 longAccumulate(x, null, uncontended, index);
65 }
66 }
67
68 /**
69 * Equivalent to {@code add(1)}.
70 */
71 public void increment() {
72 add(1L);
73 }
74
75 /**
76 * Equivalent to {@code add(-1)}.
77 */
78 public void decrement() {
79 add(-1L);
80 }
81
82 /**
83 * Returns the current sum. The returned value is <em>NOT</em> an
84 * atomic snapshot; invocation in the absence of concurrent
85 * updates returns an accurate result, but concurrent updates that
86 * occur while the sum is being calculated might not be
87 * incorporated.
88 *
89 * @return the sum
90 */
91 public long sum() {
92 Cell[] cs = cells;
93 long sum = base;
94 if (cs != null) {
95 for (Cell c : cs)
96 if (c != null)
97 sum += c.value;
98 }
99 return sum;
100 }
101
102 /**
103 * Resets variables maintaining the sum to zero. This method may
104 * be a useful alternative to creating a new adder, but is only
105 * effective if there are no concurrent updates. Because this
106 * method is intrinsically racy, it should only be used when it is
107 * known that no threads are concurrently updating.
108 */
109 public void reset() {
110 Cell[] cs = cells;
111 base = 0L;
112 if (cs != null) {
113 for (Cell c : cs)
114 if (c != null)
115 c.reset();
116 }
117 }
118
119 /**
120 * Equivalent in effect to {@link #sum} followed by {@link
121 * #reset}. This method may apply for example during quiescent
122 * points between multithreaded computations. If there are
123 * updates concurrent with this method, the returned value is
124 * <em>not</em> guaranteed to be the final value occurring before
125 * the reset.
126 *
127 * @return the sum
128 */
129 public long sumThenReset() {
130 Cell[] cs = cells;
131 long sum = getAndSetBase(0L);
132 if (cs != null) {
133 for (Cell c : cs) {
134 if (c != null)
135 sum += c.getAndSet(0L);
136 }
137 }
138 return sum;
139 }
140
141 /**
142 * Returns the String representation of the {@link #sum}.
143 * @return the String representation of the {@link #sum}
144 */
145 public String toString() {
146 return Long.toString(sum());
147 }
148
149 /**
150 * Equivalent to {@link #sum}.
151 *
152 * @return the sum
153 */
154 public long longValue() {
155 return sum();
156 }
157
158 /**
159 * Returns the {@link #sum} as an {@code int} after a narrowing
160 * primitive conversion.
161 */
162 public int intValue() {
163 return (int)sum();
164 }
165
166 /**
167 * Returns the {@link #sum} as a {@code float}
168 * after a widening primitive conversion.
169 */
170 public float floatValue() {
171 return (float)sum();
172 }
173
174 /**
175 * Returns the {@link #sum} as a {@code double} after a widening
176 * primitive conversion.
177 */
178 public double doubleValue() {
179 return (double)sum();
180 }
181
182 /**
183 * Serialization proxy, used to avoid reference to the non-public
184 * Striped64 superclass in serialized forms.
185 * @serial include
186 */
187 private static class SerializationProxy implements Serializable {
188 private static final long serialVersionUID = 7249069246863182397L;
189
190 /**
191 * The current value returned by sum().
192 * @serial
193 */
194 private final long value;
195
196 SerializationProxy(LongAdder a) {
197 value = a.sum();
198 }
199
200 /**
201 * Returns a {@code LongAdder} object with initial state
202 * held by this proxy.
203 *
204 * @return a {@code LongAdder} object with initial state
205 * held by this proxy
206 */
207 private Object readResolve() {
208 LongAdder a = new LongAdder();
209 a.base = value;
210 return a;
211 }
212 }
213
214 /**
215 * Returns a
216 * <a href="{@docRoot}/serialized-form.html#java.util.concurrent.atomic.LongAdder.SerializationProxy">
217 * SerializationProxy</a>
218 * representing the state of this instance.
219 *
220 * @return a {@link SerializationProxy}
221 * representing the state of this instance
222 */
223 private Object writeReplace() {
224 return new SerializationProxy(this);
225 }
226
227 /**
228 * @param s the stream
229 * @throws java.io.InvalidObjectException always
230 */
231 private void readObject(java.io.ObjectInputStream s)
232 throws java.io.InvalidObjectException {
233 throw new java.io.InvalidObjectException("Proxy required");
234 }
235
236 }