您的位置:首页 > 编程语言 > Java开发

Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类 (r)

2016-09-03 20:19 609 查看


概要

AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似。本章以AtomicLongArray对数组类型的原子类进行介绍。内容包括:
AtomicLongArray介绍和函数列表
AtomicLongArray源码分析(基于JDK1.7.0_40)
AtomicLongArray示例

转载请注明出处:http://www.cnblogs.com/skywang12345/p/3514604.html

 


AtomicLongArray介绍和函数列表

在"Java多线程系列--“JUC原子类”02之 AtomicLong原子类"中介绍过,AtomicLong是作用是对长整形进行原子操作。而AtomicLongArray的作用则是对"长整形数组"进行原子操作。

 

AtomicLongArray函数列表

// 创建给定长度的新 AtomicLongArray。
AtomicLongArray(int length)
// 创建与给定数组具有相同长度的新 AtomicLongArray,并从给定数组复制其所有元素。
AtomicLongArray(long[] array)

// 以原子方式将给定值添加到索引 i 的元素。
long addAndGet(int i, long delta)
// 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
boolean compareAndSet(int i, long expect, long update)
// 以原子方式将索引 i 的元素减1。
long decrementAndGet(int i)
// 获取位置 i 的当前值。
long get(int i)
// 以原子方式将给定值与索引 i 的元素相加。
long getAndAdd(int i, long delta)
// 以原子方式将索引 i 的元素减 1。
long getAndDecrement(int i)
// 以原子方式将索引 i 的元素加 1。
long getAndIncrement(int i)
// 以原子方式将位置 i 的元素设置为给定值,并返回旧值。
long getAndSet(int i, long newValue)
// 以原子方式将索引 i 的元素加1。
long incrementAndGet(int i)
// 最终将位置 i 的元素设置为给定值。
void lazySet(int i, long newValue)
// 返回该数组的长度。
int length()
// 将位置 i 的元素设置为给定值。
void set(int i, long newValue)
// 返回数组当前值的字符串表示形式。
String toString()
// 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
boolean    weakCompareAndSet(int i, long expect, long update)


 


AtomicLongArray源码分析(基于JDK1.7.0_40)

AtomicLongArray的完整源码



1 /*
2  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
3  *
4  *
5  *
6  *
7  *
8  *
9  *
10  *
11  *
12  *
13  *
14  *
15  *
16  *
17  *
18  *
19  *
20  *
21  *
22  *
23  */
24
25 /*
26  *
27  *
28  *
29  *
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 sun.misc.Unsafe;
38 import java.util.*;
39
40 /**
41  * A {@code long} array in which elements may be updated atomically.
42  * See the {@link java.util.concurrent.atomic} package specification
43  * for description of the properties of atomic variables.
44  * @since 1.5
45  * @author Doug Lea
46  */
47 public class AtomicLongArray implements java.io.Serializable {
48     private static final long serialVersionUID = -2308431214976778248L;
49
50     private static final Unsafe unsafe = Unsafe.getUnsafe();
51     private static final int base = unsafe.arrayBaseOffset(long[].class);
52     private static final int shift;
53     private final long[] array;
54
55     static {
56         int scale = unsafe.arrayIndexScale(long[].class);
57         if ((scale & (scale - 1)) != 0)
58             throw new Error("data type scale not a power of two");
59         shift = 31 - Integer.numberOfLeadingZeros(scale);
60     }
61
62     private long checkedByteOffset(int i) {
63         if (i < 0 || i >= array.length)
64             throw new IndexOutOfBoundsException("index " + i);
65
66         return byteOffset(i);
67     }
68
69     private static long byteOffset(int i) {
70         return ((long) i << shift) + base;
71     }
72
73     /**
74      * Creates a new AtomicLongArray of the given length, with all
75      * elements initially zero.
76      *
77      * @param length the length of the array
78      */
79     public AtomicLongArray(int length) {
80         array = new long[length];
81     }
82
83     /**
84      * Creates a new AtomicLongArray with the same length as, and
85      * all elements copied from, the given array.
86      *
87      * @param array the array to copy elements from
88      * @throws NullPointerException if array is null
89      */
90     public AtomicLongArray(long[] array) {
91         // Visibility guaranteed by final field guarantees
92         this.array = array.clone();
93     }
94
95     /**
96      * Returns the length of the array.
97      *
98      * @return the length of the array
99      */
100     public final int length() {
101         return array.length;
102     }
103
104     /**
105      * Gets the current value at position {@code i}.
106      *
107      * @param i the index
108      * @return the current value
109      */
110     public final long get(int i) {
111         return getRaw(checkedByteOffset(i));
112     }
113
114     private long getRaw(long offset) {
115         return unsafe.getLongVolatile(array, offset);
116     }
117
118     /**
119      * Sets the element at position {@code i} to the given value.
120      *
121      * @param i the index
122      * @param newValue the new value
123      */
124     public final void set(int i, long newValue) {
125         unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);
126     }
127
128     /**
129      * Eventually sets the element at position {@code i} to the given value.
130      *
131      * @param i the index
132      * @param newValue the new value
133      * @since 1.6
134      */
135     public final void lazySet(int i, long newValue) {
136         unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
137     }
138
139
140     /**
141      * Atomically sets the element at position {@code i} to the given value
142      * and returns the old value.
143      *
144      * @param i the index
145      * @param newValue the new value
146      * @return the previous value
147      */
148     public final long getAndSet(int i, long newValue) {
149         long offset = checkedByteOffset(i);
150         while (true) {
151             long current = getRaw(offset);
152             if (compareAndSetRaw(offset, current, newValue))
153                 return current;
154         }
155     }
156
157     /**
158      * Atomically sets the element at position {@code i} to the given
159      * updated value if the current value {@code ==} the expected value.
160      *
161      * @param i the index
162      * @param expect the expected value
163      * @param update the new value
164      * @return true if successful. False return indicates that
165      * the actual value was not equal to the expected value.
166      */
167     public final boolean compareAndSet(int i, long expect, long update) {
168         return compareAndSetRaw(checkedByteOffset(i), expect, update);
169     }
170
171     private boolean compareAndSetRaw(long offset, long expect, long update) {
172         return unsafe.compareAndSwapLong(array, offset, expect, update);
173     }
174
175     /**
176      * Atomically sets the element at position {@code i} to the given
177      * updated value if the current value {@code ==} the expected value.
178      *
179      * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
180      * and does not provide ordering guarantees, so is only rarely an
181      * appropriate alternative to {@code compareAndSet}.
182      *
183      * @param i the index
184      * @param expect the expected value
185      * @param update the new value
186      * @return true if successful.
187      */
188     public final boolean weakCompareAndSet(int i, long expect, long update) {
189         return compareAndSet(i, expect, update);
190     }
191
192     /**
193      * Atomically increments by one the element at index {@code i}.
194      *
195      * @param i the index
196      * @return the previous value
197      */
198     public final long getAndIncrement(int i) {
199         return getAndAdd(i, 1);
200     }
201
202     /**
203      * Atomically decrements by one the element at index {@code i}.
204      *
205      * @param i the index
206      * @return the previous value
207      */
208     public final long getAndDecrement(int i) {
209         return getAndAdd(i, -1);
210     }
211
212     /**
213      * Atomically adds the given value to the element at index {@code i}.
214      *
215      * @param i the index
216      * @param delta the value to add
217      * @return the previous value
218      */
219     public final long getAndAdd(int i, long delta) {
220         long offset = checkedByteOffset(i);
221         while (true) {
222             long current = getRaw(offset);
223             if (compareAndSetRaw(offset, current, current + delta))
224                 return current;
225         }
226     }
227
228     /**
229      * Atomically increments by one the element at index {@code i}.
230      *
231      * @param i the index
232      * @return the updated value
233      */
234     public final long incrementAndGet(int i) {
235         return addAndGet(i, 1);
236     }
237
238     /**
239      * Atomically decrements by one the element at index {@code i}.
240      *
241      * @param i the index
242      * @return the updated value
243      */
244     public final long decrementAndGet(int i) {
245         return addAndGet(i, -1);
246     }
247
248     /**
249      * Atomically adds the given value to the element at index {@code i}.
250      *
251      * @param i the index
252      * @param delta the value to add
253      * @return the updated value
254      */
255     public long addAndGet(int i, long delta) {
256         long offset = checkedByteOffset(i);
257         while (true) {
258             long current = getRaw(offset);
259             long next = current + delta;
260             if (compareAndSetRaw(offset, current, next))
261                 return next;
262         }
263     }
264
265     /**
266      * Returns the String representation of the current values of array.
267      * @return the String representation of the current values of array
268      */
269     public String toString() {
270         int iMax = array.length - 1;
271         if (iMax == -1)
272             return "[]";
273
274         StringBuilder b = new StringBuilder();
275         b.append('[');
276         for (int i = 0; ; i++) {
277             b.append(getRaw(byteOffset(i)));
278             if (i == iMax)
279                 return b.append(']').toString();
280             b.append(',').append(' ');
281         }
282     }
283
284 }


 

AtomicLongArray的代码很简单,下面仅以incrementAndGet()为例,对AtomicLong的原理进行说明。
incrementAndGet()源码如下:

public final long incrementAndGet(int i) {
return addAndGet(i, 1);
}


说明:incrementAndGet()的作用是以原子方式将long数组的索引 i 的元素加1,并返回加1之后的值。

 

addAndGet()源码如下:

public long addAndGet(int i, long delta) {
// 检查数组是否越界
long offset = checkedByteOffset(i);
while (true) {
// 获取long型数组的索引 offset 的原始值
long current = getRaw(offset);
// 修改long型值
long next = current + delta;
// 通过CAS更新long型数组的索引 offset的值。
if (compareAndSetRaw(offset, current, next))
return next;
}
}


说明:addAndGet()首先检查数组是否越界。如果没有越界的话,则先获取数组索引i的值;然后通过CAS函数更新i的值。

 

getRaw()源码如下:

private long getRaw(long offset) {
return unsafe.getLongVolatile(array, offset);
}


说明:unsafe是通过Unsafe.getUnsafe()返回的一个Unsafe对象。通过Unsafe的CAS函数对long型数组的元素进行原子操作。如compareAndSetRaw()就是调用Unsafe的CAS函数,它的源码如下:

private boolean compareAndSetRaw(long offset, long expect, long update) {
return unsafe.compareAndSwapLong(array, offset, expect, update);
}


 


AtomicLongArray示例

1 // LongArrayTest.java的源码
2 import java.util.concurrent.atomic.AtomicLongArray;
3
4 public class LongArrayTest {
5
6     public static void main(String[] args){
7
8         // 新建AtomicLongArray对象
9         long[] arrLong = new long[] {10, 20, 30, 40, 50};
10         AtomicLongArray ala = new AtomicLongArray(arrLong);
11
12         ala.set(0, 100);
13         for (int i=0, len=ala.length(); i<len; i++)
14             System.out.printf("get(%d) : %s\n", i, ala.get(i));
15
16         System.out.printf("%20s : %s\n", "getAndDecrement(0)", ala.getAndDecrement(0));
17         System.out.printf("%20s : %s\n", "decrementAndGet(1)", ala.decrementAndGet(1));
18         System.out.printf("%20s : %s\n", "getAndIncrement(2)", ala.getAndIncrement(2));
19         System.out.printf("%20s : %s\n", "incrementAndGet(3)", ala.incrementAndGet(3));
20
21         System.out.printf("%20s : %s\n", "addAndGet(100)", ala.addAndGet(0, 100));
22         System.out.printf("%20s : %s\n", "getAndAdd(100)", ala.getAndAdd(1, 100));
23
24         System.out.printf("%20s : %s\n", "compareAndSet()", ala.compareAndSet(2, 31, 1000));
25         System.out.printf("%20s : %s\n", "get(2)", ala.get(2));
26     }
27 }


运行结果

get(0) : 100
get(1) : 20
get(2) : 30
get(3) : 40
get(4) : 50
getAndDecrement(0) : 100
decrementAndGet(1) : 19
getAndIncrement(2) : 30
incrementAndGet(3) : 41
addAndGet(100) : 199
getAndAdd(100) : 19
compareAndSet() : true
get(2) : 1000


 AtomicLongArray
/*
* @(#)AtomicLongArray.java	1.12 06/06/15
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/

package java.util.concurrent.atomic;
import sun.misc.Unsafe;
import java.util.*;

/**
* A {@code long} array in which elements may be updated atomically.
* See the {@link java.util.concurrent.atomic} package specification
* for description of the properties of atomic variables.
* @since 1.5
* @author Doug Lea
*/
public class AtomicLongArray implements java.io.Serializable {
private static final long serialVersionUID = -2308431214976778248L;

// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final int base = unsafe.arrayBaseOffset(long[].class);  // 数组首地址偏移
private static final int scale = unsafe.arrayIndexScale(long[].class); //数组元素增量地址
private final long[] array;

//越界检查,以及返回索引i元素的地址
private long rawIndex(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
return base + i * scale;
}

/**
* Creates a new AtomicLongArray of given length.
*
* @param length the length of the array
*/
public AtomicLongArray(int length) {
array = new long[length];
// must perform at least one volatile write to conform to JMM
if (length > 0)
unsafe.putLongVolatile(array, rawIndex(0), 0);  //初始化为0
}

/**
* Creates a new AtomicLongArray with the same length as, and
* all elements copied from, the given array.
*
* @param array the array to copy elements from
* @throws NullPointerException if array is null
*/
public AtomicLongArray(long[] array) {  //构造函数
if (array == null)
throw new NullPointerException();
int length = array.length;
this.array = new long[length];
if (length > 0) {
int last = length-1;
for (int i = 0; i < last; ++i)
this.array[i] = array[i];
// Do the last write as volatile
unsafe.putLongVolatile(this.array, rawIndex(last), array[last]);
}
}

/**
* Returns the length of the array.
*
* @return the length of the array
*/
public final int length() {  //长度
return array.length;
}

/**
* Gets the current value at position {@code i}.
*
* @param i the index
* @return the current value
*/
public final long get(int i) {
return unsafe.getLongVolatile(array, rawIndex(i));  //array,索引i元素的地址
}

/**
* Sets the element at position {@code i} to the given value.
*
* @param i the index
* @param newValue the new value
*/
public final void set(int i, long newValue) {
unsafe.putLongVolatile(array, rawIndex(i), newValue); //array,索引i元素的地址,新值
}

/**
* Eventually sets the element at position {@code i} to the given value.
*
* @param i the index
* @param newValue the new value
* @since 1.6
*/
public final void lazySet(int i, long newValue) {
unsafe.putOrderedLong(array, rawIndex(i), newValue);
}

/**
* Atomically sets the element at position {@code i} to the given value
* and returns the old value.
*
* @param i the index
* @param newValue the new value
* @return the previous value
*/
public final long getAndSet(int i, long newValue) {
while (true) {
long current = get(i);
if (compareAndSet(i, current, newValue))
return current;
}
}

/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param i the index
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, long expect, long update) {
return unsafe.compareAndSwapLong(array, rawIndex(i),expect, update);
}

/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
* @param i the index
* @param expect the expected value
* @param update the new value
* @return true if successful.
*/
public final boolean weakCompareAndSet(int i, long expect, long update) {
return compareAndSet(i, expect, update);
}

/**
* Atomically increments by one the element at index {@code i}.
*
* @param i the index
* @return the previous value
*/
public final long getAndIncrement(int i) {
while (true) {
long current = get(i);
long next = current + 1;
if (compareAndSet(i, current, next))
return current;
}
}

/**
* Atomically decrements by one the element at index {@code i}.
*
* @param i the index
* @return the previous value
*/
public final long getAndDecrement(int i) {
while (true) {
long current = get(i);
long next = current - 1;
if (compareAndSet(i, current, next))
return current;
}
}

/**
* Atomically adds the given value to the element at index {@code i}.
*
* @param i the index
* @param delta the value to add
* @return the previous value
*/
public final long getAndAdd(int i, long delta) {
while (true) {
long current = get(i);
long next = current + delta;
if (compareAndSet(i, current, next))
return current;
}
}

/**
* Atomically increments by one the element at index {@code i}.
*
* @param i the index
* @return the updated value
*/
public final long incrementAndGet(int i) {
while (true) {
long current = get(i);
long next = current + 1;
if (compareAndSet(i, current, next))
return next;
}
}

/**
* Atomically decrements by one the element at index {@code i}.
*
* @param i the index
* @return the updated value
*/
public final long decrementAndGet(int i) {
while (true) {
long current = get(i);
long next = current - 1;
if (compareAndSet(i, current, next))
return next;
}
}

/**
* Atomically adds the given value to the element at index {@code i}.
*
* @param i the index
* @param delta the value to add
* @return the updated value
*/
public long addAndGet(int i, long delta) {
while (true) {
long current = get(i);
long next = current + delta;
if (compareAndSet(i, current, next))
return next;
}
}

/**
* Returns the String representation of the current values of array.
* @return the String representation of the current values of array.
*/
public String toString() {
if (array.length > 0) // force volatile read
get(0);
return Arrays.toString(array);
}

}


/*

 * @(#)AtomicIntegerArray.java 1.12 06/06/15

 *

 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.

 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.

 */

package java.util.concurrent.atomic;

import sun.misc.Unsafe;

import java.util.*;

/**

 * An {@code int} array in which elements may be updated atomically.

 * See the {@link java.util.concurrent.atomic} package

 * specification for description of the properties of atomic

 * variables.

 * @since 1.5

 * @author Doug Lea

 */

public class AtomicIntegerArray implements java.io.Serializable {

    private static final long serialVersionUID = 2862133569453604235L;

   // setup to use Unsafe.compareAndSwapInt for updates

    private static final Unsafe unsafe = Unsafe.getUnsafe();

    private static final int base = unsafe.arrayBaseOffset(int[].class);

    private static final int scale = unsafe.arrayIndexScale(int[].class);

    private final int[] array;

    private long rawIndex(int i) {

        if (i < 0 || i >= array.length)

            throw new IndexOutOfBoundsException("index " + i);

        return base + i * scale;

    }

    /**

     * Creates a new AtomicIntegerArray of given length.

     *

     * @param length the length of the array

     */

    public AtomicIntegerArray(int length) {

        array = new int[length];

        // must perform at least one volatile write to conform to JMM

        if (length > 0)

            unsafe.putIntVolatile(array, rawIndex(0), 0);

    }

    /**

     * Creates a new AtomicIntegerArray with the same length as, and

     * all elements copied from, the given array.

     *

     * @param array the array to copy elements from

     * @throws NullPointerException if array is null

     */

    public AtomicIntegerArray(int[] array) {

        if (array == null)

            throw new NullPointerException();

        int length = array.length;

        this.array = new int[length];

        if (length > 0) {

            int last = length-1;

            for (int i = 0; i < last; ++i)

                this.array[i] = array[i];

            // Do the last write as volatile

            unsafe.putIntVolatile(this.array, rawIndex(last), array[last]);

        }

    }

    /**

     * Returns the length of the array.

     *

     * @return the length of the array

     */

    public final int length() {

        return array.length;

    }

    /**

     * Gets the current value at position {@code i}.

     *

     * @param i the index

     * @return the current value

     */

    public final int get(int i) {

        return unsafe.getIntVolatile(array, rawIndex(i));

    }

    /**

     * Sets the element at position {@code i} to the given value.

     *

     * @param i the index

     * @param newValue the new value

     */

    public final void set(int i, int newValue) {

        unsafe.putIntVolatile(array, rawIndex(i), newValue);

    }

    /**

     * Eventually sets the element at position {@code i} to the given value.

     *

     * @param i the index

     * @param newValue the new value

     * @since 1.6

     */

    public final void lazySet(int i, int newValue) {

        unsafe.putOrderedInt(array, rawIndex(i), newValue);

    }

    /**

     * Atomically sets the element at position {@code i} to the given

     * value and returns the old value.

     *

     * @param i the index

     * @param newValue the new value

     * @return the previous value

     */

    public final int getAndSet(int i, int newValue) {

        while (true) {

            int current = get(i);

            if (compareAndSet(i, current, newValue))

                return current;

        }

    }

    /**

     * Atomically sets the element at position {@code i} to the given

     * updated value if the current value {@code ==} the expected value.

     *

     * @param i the index

     * @param expect the expected value

     * @param update the new value

     * @return true if successful. False return indicates that

     * the actual value was not equal to the expected value.

     */

    public final boolean compareAndSet(int i, int expect, int update) {

        return unsafe.compareAndSwapInt(array, rawIndex(i),

                                        expect, update);

    }

    /**

     * Atomically sets the element at position {@code i} to the given

     * updated value if the current value {@code ==} the expected value.

     *

     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>

     * and does not provide ordering guarantees, so is only rarely an

     * appropriate alternative to {@code compareAndSet}.

     *

     * @param i the index

     * @param expect the expected value

     * @param update the new value

     * @return true if successful.

     */

    public final boolean weakCompareAndSet(int i, int expect, int update) {

        return compareAndSet(i, expect, update);

    }

    /**

     * Atomically increments by one the element at index {@code i}.

     *

     * @param i the index

     * @return the previous value

     */

    public final int getAndIncrement(int i) {

        while (true) {

            int current = get(i);

            int next = current + 1;

            if (compareAndSet(i, current, next))

                return current;

        }

    }

    /**

     * Atomically decrements by one the element at index {@code i}.

     *

     * @param i the index

     * @return the previous value

     */

    public final int getAndDecrement(int i) {

        while (true) {

            int current = get(i);

            int next = current - 1;

            if (compareAndSet(i, current, next))

                return current;

        }

    }

    /**

     * Atomically adds the given value to the element at index {@code i}.

     *

     * @param i the index

     * @param delta the value to add

     * @return the previous value

     */

    public final int getAndAdd(int i, int delta) {

        while (true) {

            int current = get(i);

            int next = current + delta;

            if (compareAndSet(i, current, next))

                return current;

        }

    }

    /**

     * Atomically increments by one the element at index {@code i}.

     *

     * @param i the index

     * @return the updated value

     */

    public final int incrementAndGet(int i) {

        while (true) {

            int current = get(i);

            int next = current + 1;

            if (compareAndSet(i, current, next))

                return next;

        }

    }

    /**

     * Atomically decrements by one the element at index {@code i}.

     *

     * @param i the index

     * @return the updated value

     */

    public final int decrementAndGet(int i) {

        while (true) {

            int current = get(i);

            int next = current - 1;

            if (compareAndSet(i, current, next))

                return next;

        }

    }

    /**

     * Atomically adds the given value to the element at index {@code i}.

     *

     * @param i the index

     * @param delta the value to add

     * @return the updated value

     */

    public final int addAndGet(int i, int delta) {

        while (true) {

            int current = get(i);

            int next = current + delta;

            if (compareAndSet(i, current, next))

                return next;

        }

    }

    /**

     * Returns the String representation of the current values of array.

     * @return the String representation of the current values of array.

     */

    public String toString() {

        if (array.length > 0) // force volatile read

            get(0);

        return Arrays.toString(array);

    }

}

更多内容

1. Java多线程系列--“JUC原子类”01之 框架

2. Java多线程系列--“JUC原子类”02之 AtomicLong原子类

3. Java多线程系列目录(共xx篇)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: