[Java多线程]-J.U.C.atomic包下的AtomicInteger,AtomicLong等类的源码解析
2017-03-24 11:17
525 查看
Atomic原子类:为基本类型的封装类Boolean,Integer,Long,对象引用等提供原子操作.
AtomicInteger源码:
AtomicReference源码
除了类型是个对象的之外,方法使用和AtomicInteger一模一样:
AtomicReference的使用:
运行结果:
第一步:先获取pigTest的toString(),和hashCode,结果是【猪坚强,2】,hashCode:779824645【我们发现hashCode居然==pig_hashCode】
第二步:进行CAS修改为pig2结果为true,再进行一次结果为FALSE,
第三步:获取pigTest的toString(),和hashCode,结果是【猪八戒,2】,hashCode:420110874【我们发现hashCode居然==pig2_hashCode】
结果说明了:pigtest是一个指向对象引用的引用,利用CAS操作可以修改pigTest指向的对象引用从而改变自身指向的对象。第一次CAS成功将pigtest指向的pig修改成了pig2.第二次CAS操作失败了,可以保证多线程并发时的安全问题。
利用CAS+voliate+native的机制保证数据操作的原子性,可见性和一致性。voliate使变量可见,CAS调用unsafe中的native方法访问系统底层的实现。unsafe中的这些方法直接操作内存,运用不当可能造成很大的问题。
其实从Atomic包中的原子类的探索中,只是想引出CAS这个概念,CAS同样提供了一种线程安全的机制,而它不同于Synchonrized,synchonrized被称之为重量级锁,原因是因为粒度太强,加锁就代表着线程阻塞,高并发访问时带来的性能问题是硬伤。
为了解决这种问题出现了两种机制:一种就是CAS,另一种是锁优化。
CAS是将阻塞下降到了底层CPU上(纯属个人理解,因为看到有权威是说存在阻塞的,可能让别的线程知道已经更改了数据并且更新失败也是一种阻塞吧),语言层面访问效率远远低于系统内部硬件上,尽管同样是阻塞,在系统内部加锁解锁的效率要高很多。但是需要的是硬件支持,不过现在绝大部分CPU都已经支持CAS了。
unsafe类:http://www.cnblogs.com/mickole/articles/3757278.html大家可以看这篇博客。
一、Atomic包下的所有类如下表:
类摘要 | |
AtomicBoolean | 可以用原子方式更新的 boolean值。 |
AtomicInteger | 可以用原子方式更新的 int值。 |
AtomicIntegerArray | 可以用原子方式更新其元素的 int数组。 |
AtomicIntegerFieldUpdater<T> | 基于反射的实用工具,可以对指定类的指定 volatileint字段进行原子更新。 |
AtomicLong | 可以用原子方式更新的 long值。 |
AtomicLongArray | 可以用原子方式更新其元素的 long数组。 |
AtomicLongFieldUpdater<T> | 基于反射的实用工具,可以对指定类的指定 volatilelong字段进行原子更新。 |
AtomicMarkableReference<V> | AtomicMarkableReference维护带有标记位的对象引用,可以原子方式对其进行更新。 |
AtomicReference<V> | 可以用原子方式更新的对象引用。 |
AtomicReferenceArray<E> | 可以用原子方式更新其元素的对象引用数组。 |
AtomicReferenceFieldUpdater<T,V> | 基于反射的实用工具,可以对指定类的指定 volatile字段进行原子更新。 |
AtomicStampedReference<V> | AtomicStampedReference维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。 |
二、AtomicInteger源码分析和基本的方法使用:
Atomicinteger类中的方法列表:构造方法摘要 |
---|
AtomicInteger() 创建具有初始值 0的新 AtomicInteger。 |
AtomicInteger(int initialValue) 创建具有给定初始值的新 AtomicInteger。 |
方法摘要 | |
int | addAndGet(int delta) 以原子方式将给定值与当前值相加。 |
boolean | compareAndSet(int expect,int update) 如果当前值 ==预期值,则以原子方式将该值设置为给定的更新值。 |
int | decrementAndGet() 以原子方式将当前值减 1。 |
double | doubleValue() 以 double形式返回指定的数值。 |
float | floatValue() 以 float形式返回指定的数值。 |
int | get() 获取当前值。 |
int | getAndAdd(int delta) 以原子方式将给定值与当前值相加。 |
int | getAndDecrement() 以原子方式将当前值减 1。 |
int | getAndIncrement() 以原子方式将当前值加 1。 |
int | getAndSet(int newValue) 以原子方式设置为给定值,并返回旧值。 |
int | incrementAndGet() 以原子方式将当前值加 1。 |
int | intValue() 以 int形式返回指定的数值。 |
void | lazySet(int newValue) 最后设置为给定值。 |
long | longValue() 以 long形式返回指定的数值。 |
void | set(int newValue) 设置为给定值。 |
String | toString() 返回当前值的字符串表示形式。 |
boolean | weakCompareAndSet(int expect,int update) 如果当前值 ==预期值,则以原子方式将该设置为给定的更新值。 |
从类 java.lang.Number 继承的方法 |
---|
byteValue, shortValue |
从类 java.lang.Object 继承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
/**
* An object reference that 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
* @param <V> The type of object referred to by this reference
*/
public class AtomicReference<V> implements java.io.Serializable {
private static finallong serialVersionUID = -1848883965231344442L;
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static finallong valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicReference.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile V value;
/**
* Creates a new AtomicReference with the given initial value.
*
* @param initialValue the initial value
*/
public AtomicReference(V initialValue) {
value = initialValue;
}
/**
* Creates a new AtomicReference with null initial value.
*/
public AtomicReference() {
}
/**
* Gets the current value.
*
* @return the current value
*/
public final V get() {
return value;
}
/**
* Sets to the given value.
*
* @param newValue the new value
*/
public finalvoid set(V newValue) {
value = newValue;
}
/**
* Eventually sets to the given value.
*
* @param newValue the new value
* @since 1.6
*/
public finalvoid lazySet(V newValue) {
unsafe.putOrderedObject(this, valueOffset, newValue);
}
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
* @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 finalboolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, 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 expect the expected value
* @param update the new value
* @return true if successful.
*/
public finalboolean weakCompareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
public final V getAndSet(V newValue) {
while (true) {
V x = get();
if (compareAndSet(x, newValue))
return x;
}
}
/**
* Returns the String representation of the current value.
* @return the String representation of the current value.
*/
public String toString() {
return String.valueOf(get());
}
}
AtomicReference源码
除了类型是个对象的之外,方法使用和AtomicInteger一模一样:
AtomicReference的使用:
import java.util.concurrent.atomic.AtomicReference;
public class AtomTest {
private static AtomicReference<Pig> pigtest;
public staticvoid main(String[] args) {
Pig pig = new Pig("猪坚强", 2);
Pig pig2 = new Pig("猪八戒", 2);
System.out.println("pig_hashCode:"+pig.hashCode());
System.out.println("pig2_hashCode:"+pig2.hashCode());
AtomTest.pigtest = new AtomicReference<Pig>(pig);
System.out.println(pigtest.get().toString());
System.out.println(pigtest.get().hashCode());
System.out.println(pigtest.compareAndSet(pig, pig2));
System.out.println(pigtest.compareAndSet(pig, pig2));
System.out.println(pigtest.get().toString());
System.out.println(pigtest.get().hashCode());
}
}
运行结果:
pig_hashCode:779824645 pig2_hashCode:420110874 [猪坚强,2] 779824645 true false [猪八戒,2] 420110874
第一步:先获取pigTest的toString(),和hashCode,结果是【猪坚强,2】,hashCode:779824645【我们发现hashCode居然==pig_hashCode】
第二步:进行CAS修改为pig2结果为true,再进行一次结果为FALSE,
第三步:获取pigTest的toString(),和hashCode,结果是【猪八戒,2】,hashCode:420110874【我们发现hashCode居然==pig2_hashCode】
结果说明了:pigtest是一个指向对象引用的引用,利用CAS操作可以修改pigTest指向的对象引用从而改变自身指向的对象。第一次CAS成功将pigtest指向的pig修改成了pig2.第二次CAS操作失败了,可以保证多线程并发时的安全问题。
五、总结:
Atomic包下内容并不复杂,一句话来说就是提供了CAS无锁的安全访问机制。表现出来的是通过期望值E与内存值M作比较,相同则修改内存值M为更新值U。四个参数:当前对象this,偏移量V,期望值E,更新值U。利用CAS+voliate+native的机制保证数据操作的原子性,可见性和一致性。voliate使变量可见,CAS调用unsafe中的native方法访问系统底层的实现。unsafe中的这些方法直接操作内存,运用不当可能造成很大的问题。
其实从Atomic包中的原子类的探索中,只是想引出CAS这个概念,CAS同样提供了一种线程安全的机制,而它不同于Synchonrized,synchonrized被称之为重量级锁,原因是因为粒度太强,加锁就代表着线程阻塞,高并发访问时带来的性能问题是硬伤。
为了解决这种问题出现了两种机制:一种就是CAS,另一种是锁优化。
CAS是将阻塞下降到了底层CPU上(纯属个人理解,因为看到有权威是说存在阻塞的,可能让别的线程知道已经更改了数据并且更新失败也是一种阻塞吧),语言层面访问效率远远低于系统内部硬件上,尽管同样是阻塞,在系统内部加锁解锁的效率要高很多。但是需要的是硬件支持,不过现在绝大部分CPU都已经支持CAS了。
unsafe类:http://www.cnblogs.com/mickole/articles/3757278.html大家可以看这篇博客。
相关文章推荐
- Java的多线程编程模型之AtomicInteger
- Java中对AtomicInteger和int值在多线程下递增操作的测试
- Java源码解析Integer方法解读
- java.util.concurrent.atomic.AtomicInteger使用整理与解析
- Java 多线程10:CAS 与 AtomicInteger(乐观锁)
- 【Java多线程】AtomicInteger使用
- lesson8:AtomicInteger源码解析及性能分析
- [Java多线程]-Thread和Runable源码解析之基本方法的运用实例
- java.util.concurrent.atomic 并发包下的原子操作类(AtomicBoolean,AtomicInteger,AtomicLong......))
- 深入源码-java数据类型-8种基本数据类型二:Integer源码解析
- java多线程之AtomicInteger
- Java AtomicInteger源码分析
- Java中Integer的变量比较源码解析
- [Java多线程]-线程池的基本使用和部分源码解析(创建,执行原理)
- Java的多线程编程模型5--从AtomicInteger开始
- Java并发-AtomicInteger源码分析
- JDK 源码解析 —— AtomicInteger
- 【JDK】:java.lang.Integer源码解析
- java 多线程 AtomicInteger原子变量
- Java Integer.highestOneBit(int num) 源码解析