Java并发编程艺术 7 Java的13个原子操作类

第7章 Java的13个原子操作类

原子更新基本数据类型
AtomticBoolean    AtomicInteger   AtomicLong
AtomicInteger aint = new AtomicInteger(10);
aint.incrementAndGet();    //原子方式将当前值加1,返回自增后的  ++i
aint.decrementAndGet();    //原子方式将当前值减1,返回自减后的  --i
aint.getAndIncrement();    //返回自增前的 i++
aint.getAndDecrement();
aint.addAndGet(5);
aint.addAndGet(-5) ;
aint.compareAndSet(17, 5);  //如果输入的值等于预期值,返回true,并原子的方式设置为输入值
aint.get();                //获取当前值


原子更新数组
AtomicIntegerArray   AtomicLongArray  AtomicReferenceArray

int[] values = new int[]{1,2,3,4,5};
AtomicIntegerArray ai = new AtomicIntegerArray(values);
System.out.println(ai.addAndGet(0, 2));     //3
System.out.println(ai.getAndIncrement(1));  //2
System.out.println(values[0]);              //1
AtomicIntegerArray  的操作和AtomicInteger是类似的,只是多传递了一个index
注意:数组values通过构造方法传递进去,AtomicIntegerArray  会根据数组复制一份。所以AtomicIntegerArray内部数组进行修改的时候,不会影响原先的数组。


原子更新引用类型
AtomicReference 原子更新引用类型
AtomicReferenceFieldUpdate:原子更新引用类型里的字段。
AtomicMarkableReference:原子更新带有标记位的引用类型。

AtomicReference<User> auser = new AtomicReference<AtomicTest.User>();
User user = new User("mm", "hangzhou", 5);
auser.set(user);                 //原子方式设置对象
System.out.println("new name: "+auser.get().getName());   //原子方式获取对象
System.out.println("new age: "+auser.get().getAge());
User useru = new User("dd", "ningbo", 15);
User old = auser.getAndSet(useru);                        //获取原有对象,设置新的对象。
System.out.println("old name: "+old.getName());
System.out.println("update name: "+auser.get().getName());
System.out.println("update age: "+auser.get().getAge());
auser.compareAndSet(useru, new User("", "", 0));
如果对useru对象进行改变,auser对应数据也会发生改变。与AtomicIntegerArray不同,AtomicReference与原先的对象是绑定的。同时发生变化。

AtomicReferenceFieldUpdater<User, String> nameUp = AtomicReferenceFieldUpdater.newUpdater(User.class, String.class,"name" );
nameUp.compareAndSet(useru, "dd", "ddd");
System.out.println(useru.getName());
AtomicReferenceFieldUpdater初始化要求传入三个参数:字段所属的对象Class,字段Class,字段名。
基于反射。要求字段必须是volatile修饰,并且不能是private

AtomicMarkableReference<User> amuser = new AtomicMarkableReference<AtomicTest.User>(user, false);
amuser.set(useru, true);
System.out.println(amuser.getReference().getName());
AtomicMarkableReference和AtomicReference相比增加了个boolean类型的标记位。

static class User{
     public volatile String name;
     public volatile String addr;
     public volatile int age;
}
为了避免CAS过程中的ABA问题,并发包提供了两个类,AtomicStampedReference和AtomicMarkableReference。前者相当于一个[引用,integer]的二元组,后者相当于一个[引用,boolean]的二元组。
AtomicStampedReference可用来作为带版本号的原子引用,而AtomicMarkableReference可用于表示如:已删除的节点。

 注:ABA问题是指在CAS操作过程中,假设我们想要把目标值由1改为2,一般过程是检测目标值是否为1,如果为1就将其设置为2。但可能在检测之前目标值变成了3,然后又变成了1,检测过程并不能察觉到这种变化。这一般不会有什么影响,但在某些情况下也可能会是一个问题。

原子更新字段类型
AtomicIntegerFieldUpdate:原子更新整形的字段的更新器
AtomicLongFieldUpdate: 
AtomicStampedReference: 原子更新带有版本号的引用类型。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值