小学生手工制作大全,三重门,z4-理财招式教你玩,新时代,新理财教育

admin 2个月前 ( 07-12 03:58 ) 0条评论
摘要: 本文讲述Atomic系列的类的实现以及使用方法,其中包含:基本类:AtomicInteger、AtomicLong、AtomicBoolean;引用类型:AtomicReferen...

在java6今后咱们不光触摸到了Lock相关的锁,也触摸到了许多愈加达观的原子修正操作,也便是在修正时咱们只需求确保它的那个瞬间是安全的即可,经过相应的包装后能够再处理方针的并发修正,以及并发中的ABA问题,本文叙述Atomic系列的类的完结以及运用办法,其间包含:

底子类:AtomicInteger、AtomicLong、AtomicBoolean;

引证类型:AtomicReference、AtomicReference的ABA实例、AtomicStampedRerence、AtomicMarkableReference;

数组类型:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray

特点原子修正器(Updater):AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater

看到这么多类,你是否觉得很困惑,其实没什么,由于你只需求看懂一个,其他的办法和运用都是迥然不同的,相关的类会介绍他们之间的差异在哪里,在运用中需求留意的当地即可。

在运用Atomic系列前,咱们需求先知道一个东西便是Unsafe类,全名为:sun.misc.Unsafe,这个类包含了许多的对C代码的操作,包含许多直接内存分配以及原子操作的调用,而它之所以标记为非安全的,是告知你这个里边许多的办法调用都会存在安全隐患,需求当心运用,不然会导致严峻的成果,例如在经过unsafe分配内存的时分,假设自己指定某些区域或许会导致一些相似C++相同的指针越界到其他进程的问题,不过它的具体运用并不是本文的要点,本文要点是Atomic系列的内容大多会依据面瘫老公unsafe类中的以下几个本地办法来操作:

方针的引证进行比照后交流,交流成功回来true,交流失利回来false,这个交流进程彻底是原子的,在CPU上核算完成果后,都会比照内存的成果是否仍是原先的值,若不是,则以为不能替换,由于变量是volatile类型所以终究写入的数据会被其他线程看到,所以一个线程修正成功后,其他线程就发现自己修正失利了。

参数1:方针地点的类自身的方针(一般这儿是对一个方针的特点做修正,才会呈现并发,所以该方针所存在的类也是有一个方针的)

参数2:这个特点在这个方针里边的相对廉价量方位,其实比照时是比照内存单元,所以需求特点的开端方位,而引证便是修正引证地址(依据OS、VM位数和参数装备决议宽度一般是4-8个字节),int便是修正相关的4个字节,而long便是修正相关的8个字节。

获取偏移量也是经过unsafe的一个办法:objectFieldOffset(Fieldfield)来获取特点在方针中的偏移量;静态变量需求经过:staticFieldOffset(Field field)获取,调用的总办法是:fieldOffset(Fieldfield)

参数3:修正的引证的原始值,用于比照本来的引证和要修正的方针是否共同。

参数4:修正的方针值,要将数据修正成什么。

public final native boolean compareAndSwapObject(Object paramObject1, long paramLong, Object paramObject2, Object paramObject3);

public final native boolean compareAndSwapInt(Object paramObject, long para小学生手艺制造大全,三重门,z4-理财招式教你玩,新时代,新理财教育mLong, int paramInt1, int paramInt2);

#对long的操作,要看VM是否支撑对Long的CAS,由于有或许VM自身不支撑,若不支撑,此刻运算会变成Lock办法,不过现在VM都底子是支撑的罢了。

public final native boolean compareAndSwapLong(Object paramObject, long paramLong1, long paramLong2, long paramLong3);

咱们不引荐直接使gg187用unsafe来操作原子变量,而是经过java封装好的一些类来操作原子变量。

实例代码1:AtomicIntegerTest.java

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest {

/**

* 常见的办法列表

* @see AtomicInteger#get() 直接回来值

* @see AtomicInteger#getAndAdd(int) 添加指定的数据,回来改动前的数据

* @see AtomicInteger#getAndDecrement() 削减1,回来削减前的数据

* @see AtomicInteger#getAndIncrement() 添加1,回来添加前的数据

* @see AtomicInteger#getAndSet(int) 设置指定的数据,回来设置前的数据

*

* @see AtomicInteger#addAndGet(int) 添加指定的数据后回来添加后的数据

* @see AtomicInteger#decrementAndGet() 削减1,回来削减后的值

* @see AtomicInteger#incrementAndGet() 添加1,回来添加后的值

* @see AtomicInteger#lazySet(int) 仅仅当get时才会set

*

* @see AtomicInteg小学生手艺制造大全,三重门,z4-理财招式教你玩,新时代,新理财教育er#compareAndSet(int, int) 测验新增后比照,若添加成功则回来true不然回来false

*/

public final static AtomicInteger TEST_INTEGER = new AtomicInteger(1);

public static void main(String []args) throws InterruptedException {

final Thread []threads = new Thread[10];

for(int i = 0 ; i < 10 ; i++) {

final int num = i;

threads[i] = new Thread() {

public void run() {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

int now = TEST_INTEGER.incrementAndGet();

System.out.println("我是线程:" + num + ",我得到值了,添加后的值为:" + now);

}

};

threads[i].start();

}

for(Thread t : threads) {

t.join();

}

System.out.println("终究运转成果:" + TEST_INTEGER.get());

}

}

代码比方中模仿多个线程并发对AtomicInteger进行添加1的操作,假设这个数据是一般类型,那么添加进程中呈现的问题便是两个线程或许一起看到的数据都是同一个数据,添加完结后写回的时分,也是同一个数据,可是两个加法应当串行添加1,也便是加2的操作,甚至于愈加特别的状况是一个线程加到3后,写入,另一个线程写入了2,还越变越少,也便是不能得到正确的成果,在并发下,咱们模仿计数器,要得到准确的计数器值,就需求运用它,咱们期望得到的成果是11,能够复制代码进去运转后看到成果确实是11,顺然输出的次序或许不相同,也一起能够证明线程确实是并发运转的(仅仅在输出的时分,征用System.out这个方针也纷歧定是谁先抢到),可是终究成果确实是11。

信任你对AtomicInteger的运用有一些了解了吧,要知道更多的办法运用,请参看这段代码中界说变量方位的注释,有关于AtomicInteger的相关办法的具体注释,能够直接盯梢进去看源码,注释中运用了简略的描绘阐明晰办法的用处。

而关于AtomicLong呢,其实和AtomicInteger差不多,仅有的差异便是它处理的数据是long类型的便是了;

关于AtomicBoolean呢,办法要少一些,常见的办法就两个:

AtomicBoolean#compareAndSet(boolean, boolean) 第一个参数为原始值,第二个参数为要修正的新值,若修正成功则回来true,不然回来false

AtomicBoolean#getAndSet(boolean) 测验设置新的boolean值,直到成功停止,回来设置前的数据

由于boolean值就两个值,所以便是来回改,相对的许多添加削减的办法天然就没有了,关于运用来讲,咱们罗列一个boolean的并发修正,仅有一个线程能够修正成功的比方:

实例代码2:AtomicBooleanTest.java

import java.util.concurrent.atomic.AtomicBoolean;

public class AtomicBooleanTest {

/**

* 首要办法:

* @see AtomicBoolean#compareAndSet(boolean, boolean) 第一个参数为原始值,第二个参数为要修正的新值,若修正成功则回来true,不然回来false

* @see AtomicBoolean#getAndSet(boolean) 测验设置新的boolean值,直到成功停止,回来设置前的数据

*/

public final static AtomicBoolean TEST_BOOLEAN = new AtomicBoolean();

public static void main(String []args) {

for(int i = 0 ; i < 10 ; i++) {

new Thread() {

public void run()熊猫哥哥和功夫美少女 {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

if(TEST_BOOLEAN.compareAndSet(false, true)) {

Syg7150stem.out.println("我成功了!");

}

}

}.start();

}

}

}

这儿有10个线程,咱们让他们简直一起去征用boolean值的修正,修正成功者输出:我成功了!此刻你运转完你会发现只会输出一个“我成功了!”,阐明征用进程中达到了锁的作用。

那么几种底子类型就说完了,咱们来看看里边的完结是不是如咱们开端说的Unsafe那样,看几段源码即可,咱们看下AtomicInteger的一些源码,例如开端用的:incrementAndGet办法,这个,它的源码是:

public final int incrementAndGet() {

for (;;) {

int current = get();

int next = current + 1;

if (compareAndSet(current, next))

return next;

}

}

能够看到内部有一个死循环,只尤靖茹几岁有不断去做compareAndSet操作,直到成功停止,也便是修正的底子在compareAndSet办法里边,能够去看下相关的修正办法均是这样完结,那么看下compareAndSet办法的body部分是:

public final小振平 boolean compareAndSet(int expect, int update) {

return unsafe.compareAndSwapInt(this, valueOffset, expect, update);

}

能够看到这儿运用了unsafe的compareAndSwapInt的办法,很明显this便是指AtomicInteger当时的这个方针(这个方针不必像上面说的它不能是static和final,它无所谓的),而valueOffset的界说是这样的:

private static final long valueOffset;

static {

try {

va邵亚磊lueOffset = unsafe.objectFieldOffset

(AtomicInteger.class.getDeclaredField("value"));

} catch (Exception ex) {

throw new Error(ex); }

}

能够看出是经过咱们前面所述的objectFieldOffset办法来获取的特点偏移量,所以你自己假设界说相似的操作的时分,就要留意,这个特点不能是静态的,不然不能用这个办法来获取。

后边两个参数天然是比照值和需求修正的方针方针的地址。

其实Atomic系列你看到这儿,小学生手艺制造大全,三重门,z4-理财招式教你玩,新时代,新理财教育java层面你就知道差不多了,其他的便是特别用法和包装罢了,方才咱们说了unsafe的3个办法无非是地址和值的差异在内存层面是没有本质差异的,由于地址自身也是数字值。

为了阐明这个问题,咱们就先说Reference的运用:

咱们测验一个reference,和boolean测验办法相同,也是测验多个线程只需一个线程能修正它。

实例代码1:AtomicReferenceTest.java

import java.util.concurrent.atomic.AtomicReference;

public class AtomicReferenceTest {

/**

* 相关办法列表

* @see AtomicReference#compareAndSet(Object, Object) 比照设置值,参数1:原始值,参数2:修正方针引证

* @see AtomicReference#getAndSet(Object) 将引证的方针修正为设置的参数,直到修正成功停止,回来修正前的引证

*/

public final static AtomicReference ATOMIC_REFERENCE = new AtomicReference("abc");

public static void main(String []args) {

for(int i = 0 ; i < 100 ; i++) {

final int num = i;

new Thread() {

public void run() {

try {

Thread.sleep(Math.abs((int)(Math.random() * 100)));

} catch (InterruptedException e) {

e.printStackTrace();

}

if(ATOMIC_REFERENCE.compareAndSet("abc", new String("abc"))) {

System.out.println("我是线程:" + num + ",我获得了锁进行了方针修正!");

}

}

}.start();

}

}

}

测验成果如咱们所料,确实只需一个线程,履行,跟着代码:compareAndSet进去,发现源码中的调用是:

public final boolean compareAndSet(V expect, V update) {

return unsafe.compareA神聊海吹ndSwapObject(this, valueOffset, expect, update);

}

OK,确实和咱们上面所讲共同,那么此刻咱们又遇到了引证修正的新问题,什么问题呢?ABA问题,什么是ABA问题呢,当某些流程在处理进程中是顺向的,也便是不允许重复处理的状况下,在某些状况下导致一个数据由A变成B,再中心或许经过0-N个环节后变成了A,此刻A不允许再变成B了,由于此刻的状况现已发生了改动,例如:银行资金里边做一批账目操作,要求资金在80-100元的人,添加20元钱,时刻持续一天,也便是后台程序会不断扫描这些用户的资金是否是在这个规模,可是要求添加过的人就不能再添加了,假设添加20后,被人取出10元持续在这个规模,那么就能够无限套现出来,便是ABA问题了,相似的还有抢红包或中奖,比方每天每个人定量3个红包,中那个等级的奖的个数等等。

此刻咱们需求运用的办法就不是简略的compareAndSet操作,由于它仅仅是考虑到物理上的并发,而不是在业务逻辑上去操控次序,此刻咱们需求学习数据库的业务序列号的一些思想来处理,假设每个方针修正的次数能够记住,修正前先比照下次数是否共同再修正,那么这个问题就简略了,AtomicStampedReference类正是供给这一功用的,其实它仅仅是在AtomicReference类的再一次包装,里边添加了一层引证和计数器,其实是否为计数器彻底由自己操控,大多数咱们是让他自增的,你也能够依照自己的办法来标明版本号,下面一个比方是ABA问题的简略演示:

实例代码3(ABA问题模仿代码演示):

import java小学生手艺制造大全,三重门,z4-理财招式教你玩,新时代,新理财教育.util.concur小学生手艺制造大全,三重门,z4-理财招式教你玩,新时代,新理财教育rent.atomic.AtomicReference;

/**

* ABA问题模仿,线程并发中,导致ABA问题,处理方案是运用|AtomicMarkableReference

* 请参看相应的比方:AtomicStampedReferenceTest、AtomicMarkableReferenceTest

*

*/

public class AtomicReferenceABATest {

public final static AtomicReference ATOMIC_RE小学生手艺制造大全,三重门,z4-理财招式教你玩,新时代,新理财教育FERENCE = new AtomicReference("abc");

public static void main(String []args) {

for(int i = 0 ; i < 100 ; i++) {

final int num = i;

new Thread() {

public void run() {

try {

Thread.sleep(Math.abs((int)(Math.random() * 100)));

} catch (InterruptedException e) {

e.printStackTrace();

}

if(ATOMIC_REFERENCE.compareAndSet("abc" , "abc2")) {

System.out.println("我椰皇怎样翻开是线程:" + num + ",我获得了锁进行了方针修正!");

}

}

}.start();

}

new Thread() {

public void run() {

while(!ATOMIC_REFERENCE.compareAndSet("abc2", "abc"));

System.out.println("现已改为原始值!");

}

}.start();

}

}

代码中和本来的比方,仅有的差异便是最终添加了一个线程让他将数据修正为本来的值,并一向测验修正,直到修正成功停止,为什么没有直接用:办法呢getAndSet办法呢,由于咱们的意图是要让某个线程先将他修正为abc2后再让他修正回abc,所以需求这样做;

此刻咱们得到的成果是:

我是线程:41,我获得了锁进行了方针修正!

现已改为原始值!

我是线程:85,我获得了锁进行了方针修正!

当然你的线程编号八成和我不相同,只需征用到就对,能够发现,有两个线程修正了这个字符串,咱们是想那一堆将abc改成abc2的线程仅有一个成功,即便其他线程在他们征用时将其修正为abc,也不能再修正。

此刻咱们经过类来AtomicStampedReference处理这个问题:

实例代码4(AtomicStampedReference处理ABA问题):

import java.util.concurrent.atomic.AtomicStampedReference;

public class AtomicStampedReferenceTest {

public final static AtomicStampedReference ATOMIC_REFERENCE = new AtomicStampedReference("abc" , 0);

public static void main(String []args) {

for(int i = 0 ; i < 100 ; i++) {

final int num = i;

final int stamp = ATOMIC_REFERENCE.getStamp();

new Thread() {

public void run() {

try {

Thread.sleep(Math.abs((int)(Math.random() * 100)));

} catch (InterruptedException e) {

e.printStackTrace();

}

if(ATOMIC_REFERENCE.compareAndSet("abc" , "abc2" , stamp , stamp + 1)) {

System.out.println("我是线程:" + num + ",我获小学生手艺制造大全,三重门,z4-理财招式教你玩,新时代,新理财教育得了锁进行了方针修正!");

}

}

}.start();

}

new Thread() {

public void run() {

int stamp = ATOMIC_REFERENCE.getStamp();

while(!ATOMIC_REFERENCE.compareAndSet("abc2", "abc" , stamp , stamp + 1));

System.out.println("现已改回为原始值!");

}

}.start();

}

}

此刻再运转程序看到的成果便是咱们想要的了,发现将abc修正为abc2的线程仅有一个被拜访,尽管被修正回了原始值,可是其他线程也不会再将abc改为abc2。

而类:AtomicMarkableReference和AtomicStampedReference功用差不多,有点差异的是:它描绘愈加简略的是与否的联系,一般ABA问题只需两种状况,而AtomicStampedRefer两性生活ence是多种状况,那么为什么还要有AtomicMarkableReference呢,由于它在处理是与否上面愈加具有可读性,而AtomicStampedReference过于随意界说状况,并不便于阅览许多的是和否的联系,它能够被以为是一个计数器或状况列表等信息,java发起经过类名知道其含义,所以这个类的存在也是必要鲜艳姐妹花的,它的定小吴钱柜义便是将数据变换为true|false如下:

public final static AtomicMarkableReference ATOMIC_MARKABLE_REFERENCE = new AtomicMarkableReference("abc" , false);

操作时运用:

ATOMIC_MARKABLE_REFERENCE.compareAndSet("abc", "abc2", false, true);

好了,reference的三个类的品种都介绍了,咱们下面要开端说Atomic的数组用法,由于咱们开端提到的都是一些简略变量和底子数据,操作数组呢?假设你来规划会怎样规划,Atomic的数组要求不允许修正长度等,不像调集类那么丰厚的操作,不过它能够让你的数组上每个元素的操作肯定安全的,也便是它细化的力度仍是到数组上的元素,为你做了二次包装,所以假设你来规划,便是在原有的操作上添加一个下标拜访即可,咱们来模仿一个Integer类型的数组,即:AtomicIntegerArray

实例代码5(AtomicIntegerArrayTest.java)

import java.util.concurrent.atomic.AtomicIntegerArray;

public class AtomicIntegerArrayTest {

/**

* 常见的办法列表

* @see AtomicIntegerArray#addAndGet(int, int) 履行加法,第一个参数为数组的下标,第二个参数为添加的数量,回来添加后的成果

* @see AtomicIntegerArray#compareAndSet(int, int, int) 比照修正,参数1:数组下标,参数2:原始值,参数3,修正方针值,修正成功回来true不然false

* @see AtomicIntegerArray#decrementAndGet(int) 参数为数组下标,将数组对应数字削减1,回来削减后的数据

* @see AtomicIntegerArray#incrementAndGet(int) 参数为数组下标,将数组对应数字添加1,回来添加后的数据

*

* @see AtomicIntegerArray#getAndAdd(int, int) 和addAndGet相似,差异是回来值是改动前的数据

* @see AtomicIntegerArray#getAndDecrement(int) 和decrementAndGet相似,差异是回来改动前的数据

* @see AtomicIntegerArray#getAndIncrement(int) 和incrementAndGet相似,差异是回来改动前的数据

公孙狷介* @see AtomicIntegerArray#getAndSet(int, int) 将对应下标的数字设置为指定值,第二个参数为设置的值,回来是改动前的数据

*/

private final static AtomicIntegerArray ATOMIC_INTEGER_ARRAY = new AtomicIntegerArray(new int[]{1,2,3,4,5,6,7,8,9,10});

public static void main(S幻影前锋tring []args) throws InterruptedException {

Thread []threads = new Thread[100];

for(int i = 0 ; i < 100 ; i++) {

final int index = i % 10;

final int threadNum = i;

threads[i] = new Thread() {

public void run() {

int result = ATOMIC_INTEGER_ARRAY.addAndGet(index, index + 1);

System.out.println("线程编号为:" + threadNum + " , 对应的原始值为:" + (index + 1) + ",添加后的成果为:" + result);

}

};

threads[i].start();

}

for(Thread thread : threads) {

thread.join();

}

System.out.println("=========================>\n履行现已完结,成果列表:");

for(int i = 0 ; i < ATOMIC_INTEGER_ARRAY.length() ; i++) {

System.out.println(ATOMIC_INTEGER_ARRAY.get(i));

}

}

}

核算成果阐明:100个线程并发,每10个线程会被并发修正数组中的一个元素,也便是数组中的每个元素会被10个线程并发修正拜访,每次添加原始值的巨细,此刻运算完的成果看最终输出的敲好为原始值的11倍数,和咱们预期的共同,假设不是线程安全那么这个值什么都有或许。

而相应的类:AtomicLongArray其实和AtomicIntegerArray操作办法相似,最大差异便是它操作的数据类型是long;而AtomicRerenceArray也是这样,仅仅它办法只需两个:

AtomicReferenceArray#compareAndSet(int, Object, Object)

参数1:数组下标;

参数2:修正原始值比照;

参数3:修正方针值

修正成功回来true,不然回来false

AtomicReferenceArray#getAndSet(int, Object)

参数1:数组下标

参数2:修正的方针

修正成功停止,回来修正前的数据

到这儿你是否对数组内部的操作应该有所了解了,和最初预期相同,参数便是多了一个下标,为了彻底验证这点,盯梢到源码中能够看到:

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;

}

}

能够看到依据get(i)获取到对应的数据,然后做和一般AtomicInteger差不多的操作,get操作里边有个细节是:

public final int get(int i) {

return unsafe.getInt雾海迷踪Volatile(array, rawIndex(i));

}

这儿经过了unsafe获取依据volatile办法获取(可见性)获取一个int类型的数据,而获取的方位是由rawIndex来确认,它的源码是:

private long rawIndex(int i) {

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

throw new IndexOutOfBoundsException("index " + i);

return base + (long) i * scale;

}

能够发现这个成果是一个地址方位,为base加上一耳光偏移量,那么看看base和scale的界说为:

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

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

能够发现unsafe里边供给了对数组base的方位的获取,由于方针是有头部的,而数组还有一个长度方位,第二个很明显是一个数组元素所占用的宽度,也便是底子精度;这儿应该能够体会到unsafe所带来的强壮了吧。

本文最终要介绍的部分为Updater也便是修正器,它算是Atomic的系列的一个扩展,Atomic系列是为你界说好的一些方针,你能够运用,可是假设是他人现已在运用的方针会原先的代码需求修正为Atomic系列,此刻若悉数修正类型到对应的方针信任很费事,由于牵涉的代码会许多,此刻java供给一个外部的Updater能够对方针的特点自身的修正供给相似Atomic的操作,也便是它对这些一般的特点的操作是并发下安全的,分别由:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceUpdater,这样操作后,体系会愈加灵敏,也便是或许起重机减速机那些类的特点仅仅在某些状况下需求操控并发,许多时分不需求,可是他们的运用一般有以下几个约束:

约束1:操作的方针不能是static类型,前面提到unsafe的现已能够猜测到它提取的对错static类型的特点偏移量,假设是static类型在获取时假设没有运用对应的办法是会报错的,而这个Updater并没有运用对应的办法。

约束2:操作的方针不能是final类型的,由于final底子无法修正。

约束3:有必要是volatile类型的数据,也便是数据自身是读共同的。

约束4:特点有必要对当时的Updater地点的区域是可见的,也便是private假设不是当时类肯定是不行见的,protected假设不存在父子联系也是不行见的,default假设不是在同一个package下也是不行见的。

完结办法:经过反射找到特点,对特点进行操作,可是并不是设置accessable,所以有必要是可见的特点才干操作。

说了这么多,来个实例看看吧。

实例代码6:(AtomicIntegerFieldUpdaterTest.java)

import java.资中中药材栽培方针util.concurrent.atomic.AtomicIntegerFie舔白袜ldUpdater;

public class AtomicIntegerFieldUpdaterTest {

static class A {

volatile int intValue = 100;

}

/**

* 能够直接拜访对应的变量,进行修正和处理

* 条件:要在可拜访的区域内,假设是private或挎包拜访default类型以及非父亲类的protected均无法拜访到

* 其次拜访方针不能是static类型的变量(由于在核算特点的偏移量的时分无法核算),也不能是final类型的变量(由于底子无法修正),有必要是一般的成员变量

*

* 办法(阐明上和AtomicInteger简直共同,仅有的差异是第一个参数需求传入方针的引证)

* @see AtomicIntegerFieldUpdater#addAndGet(Object, int)

* @see AtomicIntegerFieldUpdater#compareAndSet(Object, int, int)

* @see AtomicIntegerFieldUpdater#decrementAndGet(Object)

* @see AtomicIntegerFieldUpdater#incrementAndGet(Object)

*

* @see AtomicIntegerFieldUpdater#getAndAdd(Object, int)

* @see AtomicIntegerFieldUpdater#getAndDecr性快感ement(Object)

* @see AtomicIntegerFieldUpdater#getAndIncrement(Object)

* @see AtomicIntegerFieldUpdater#getAndSet(Object, int)

*/

public final static AtomicIntegerFieldUpdater ATOMIC_INTEGER_UPDATER = AtomicIntegerFieldUpdater.newUpdater(A.class, "intValue");

public static void main(String []args) {

final A a = new A();

for(int i = 0 ; i < 100 ; i++) {

final int num = i;

new Thread() {

public void run() {

if(ATOMIC_INTEGER_UPDATER.compareAndSet(a, 100, 120)) {

System.out.println("我是线程:" + num + " 我对对应的值做了修正!");

}

}

}.start();

}

}

}

此刻你会发现只需一个线程能够对这个数据进行修正,其他的办法如上面描绘相同,完结的功用和AtomicInteger相似。

而AtomicLongFieldUpdater其实也是这样,差异在于它所操作的数据是long类型。

AtomicReferenceFieldUpdater办法较少,首要是compareAndSet以及getAndSet两个办法的运用,它的界说比数字类型的多一个参数如下:

static class A {

volatile String stringValue = "abc";

}

AtomicReferenceFieldUpdater ATOMIC_REFERENCE_FIELD_UPDATER = AtomicReferenceFieldUpdater.newUpdater(A.class, String.class, "stringValue");

能够看到,这儿传递的参数添加了一个特点的类型,由于引证的是一个方针,方针自身也有一个类型。

文章版权及转载声明:

作者:admin本文地址:http://www.ilica107.com/articles/2265.html发布于 2个月前 ( 07-12 03:58 )
文章转载或复制请以超链接形式并注明出处理财招式教你玩,新时代,新理财教育