博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JUC——原子类操作(三)
阅读量:7103 次
发布时间:2019-06-28

本文共 4901 字,大约阅读时间需要 16 分钟。

原子类操作

  既然强调了并发访问,那么就必须考虑操作系统位数:32位操作系统还是64位操作系统,对于long型数据类型而言,是64位的。但是如果现在项目运行在32位系统上,则long型数据会占用32位空间进行数据的保存。

如果现在每一个程序类里面都去使用long类型,那么进行处理的时候都需要手动进行volatile配置,那样就太麻烦了。

为了解决这样的问题,在juc里面提供了一个atomic子包,这个子包里面保存的都是原子性的操作数据,也就是说里面包含的数据类型都使用volatile进行声明。

 

原子操作分类

 原子操作:是指操作过程中不会被中断,保证数据操作是以原子方式进行的。

  • 基本数据类型:AtomicInteger, AtomicLong, AtomicBoolean
  • 数组类型:AtomicIntegerArray, AtomicLongArray, AtomicRefernceArray
  • 引用类型: AtomicReference, AtomicStampedRerence, AtomicMarkableReference
  • 对象的属性修改类型: AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater.

范例:观察“AtomicLong”类型

  实际上在使用“AtomicLong”的时候里面包含的就是“private volatile long value”.

package so.strong.concurrents;import java.util.concurrent.atomic.AtomicLong;public class StrongDemo {    public static void main(String[] args) throws Exception {        AtomicLong num = new AtomicLong(10);        System.out.println("数据自增:"+num.incrementAndGet());        System.out.println("数据自减:"+num.decrementAndGet());    }}

  如果要进行数据类型的基础数学运算也是需要通过方法进行的。

 

范例:实现基础数学运算

package so.strong.concurrents;import java.util.concurrent.atomic.AtomicLong;public class StrongDemo {    public static void main(String[] args) throws Exception {        AtomicLong num = new AtomicLong(100);        System.out.println("加法操作:"+num.addAndGet(10));        System.out.println("减法操作:"+num.addAndGet(-9));    }}

  毕竟这种操作不是原始的基本数据类型,它的操作时刻需要保证数据在多线程访问下的并发安全性。

对于原子性的处理,以上并不是它的重点,只是它的操作形式,这里面有一个最为重要的方法,CAS方法:

public final boolean compareAndSet(long expect, long update) {      return unsafe.compareAndSwapLong(this, valueOffset, expect, update);}

 

范例:观察CAS方法的使用

package so.strong.concurrents;import java.util.concurrent.atomic.AtomicLong;public class StrongDemo {    public static void main(String[] args) throws Exception {        AtomicLong num = new AtomicLong(100); //设置原子性操作        //如果现在要进行修改的内容是100,即:原始的原子类型里面为100,则使用300替换num的内容        System.out.println(num.compareAndSet(101,300));  //比较的值等于100,返回true        System.out.println(num);    }}

使用CAS方法进行内容修改的时候一定要设置一个原始的比较内容,如果内容相同才可以修改,如果现在操作的是数组也有与之对应的程序类AtomicLongArray。

AtomicLongArray有两个构造方法:

  • 动态开辟:设置数组的长度
    public AtomicLongArray(int length) {     array = new long[length];  }
  • 静态开辟:设置具体的数组内容
    public AtomicLongArray(long[] array) {    this.array = array.clone();}

     

范例:进行数组操作

package so.strong.concurrents;import java.util.concurrent.atomic.AtomicLongArray;public class StrongDemo {    public static void main(String[] args) throws Exception {        AtomicLongArray array = new AtomicLongArray(new long[]{1,2,3});        array.set(0,99); //原子性的数组必须使用set修改内容        System.out.println(array);    }}

  除了对long类型进行原子性的处理支持之外也可以对引用类型(对象)进行原子性操作。

范例:使用原子性进行对象的描述

package so.strong.concurrents;import java.util.concurrent.atomic.AtomicReference;public class StrongDemo {    public static void main(String[] args) throws Exception {        AtomicReference
ref = new AtomicReference<>(); Member memA = new Member("张三", 22); Member memB = new Member("李四", 32); ref.set(memA); ref.compareAndSet(memA, memB); //对象引用变更只得依靠地址比较“==” System.out.println(ref); }}class Member { private String name; private int age; public Member(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "name= " + this.name + ",age= " + this.age; }}

 

以上的几种类型严格来讲都算是常用的几种处理形式,但是在Java开发里面有可能会遇见一种很奇怪的问题,即:可能本身类中定义的类型不是AtomicLong,那么可以利用AtomicLongFieldUpdater类来完成。

public abstract class  AtomicLongFieldUpdater
// 抽象类AtomicLongFieldUpdater更新器
AtomicLongFieldUpdater更新器获得对象的方法:
@CallerSensitivepublic static  AtomicLongFieldUpdater newUpdater(Class tclass, String fieldName) {    Class
caller = Reflection.getCallerClass(); if (AtomicLong.VM_SUPPORTS_LONG_CAS) return new CASUpdater(tclass, fieldName, caller); else return new LockedUpdater(tclass, fieldName, caller);}

 

范例:使用AtomicLongFieldUpdater更新器

package so.strong.concurrents;import java.util.concurrent.atomic.AtomicLongFieldUpdater;public class StrongDemo {    public static void main(String[] args) throws Exception {        Book book = new Book(100001,"Java从入门到放弃");        book.setBid(200002); //修改bid        System.out.println(book);    }}class Book {    private volatile long bid; //必须追加volatile关键字    private String title;    public Book(long bid, String title) {        this.bid = bid;        this.title = title;    }    @SuppressWarnings({
"rawtypes","unchecked"}) public void setBid(long bid) { AtomicLongFieldUpdater updater = AtomicLongFieldUpdater.newUpdater(super.getClass(), "bid"); updater.compareAndSet(this, this.bid, bid);//使用CAS方法进行内容的修改 } @Override public String toString() { return "图书编号: " + this.bid + ", 名称: " + this.title; }}

 

并发访问中为了保证多位的数据类型的完整性一定要使用volatile关键字,同时在整个juc的开包里面会发现有大量的原子操作类出现。

 

转载于:https://www.cnblogs.com/itermis/p/8931665.html

你可能感兴趣的文章
制造业ERP的核心:生产控制
查看>>
物联网智能技术引领互联网新风潮
查看>>
汇量科技1172万美元收购欧洲移动游戏数据分析公司
查看>>
深度融合信息化 视频监控打击震慑犯罪
查看>>
智能家居未来已来,可没做到这点便是“鸡肋”!
查看>>
北卡一号光伏电站全容并网
查看>>
欧盟向美社交网络发出通牒 限期一月修改服务条款否则罚款
查看>>
等等AMD!英特尔最新路线图曝10nm延期
查看>>
无线领军企业的5G之路
查看>>
Android应用自动化测试——理论、工具和实践(上)
查看>>
《Clojure数据分析秘笈》——1.9节从网页中抓取文本数据
查看>>
WordPress 4.6.1 安全修复版发布
查看>>
保护普通用户上网安全 iOS版WiFi万能钥匙推出安全险
查看>>
链家跨界合作今日头条,大数据将重塑房产交易服务
查看>>
Chinapex创略宣布完成A轮融资 打造企业级数据驱动营销云平台
查看>>
Snapchat 首份成绩单表现不好,它未来还有更多“劫”要渡
查看>>
济宁用大数据“科学治气”
查看>>
联发科技与Orange合作加速物联网设备普及
查看>>
GridView全选
查看>>
我的软件测试之旅:(4)并行——自动化回归测试
查看>>