JUC——原子类操作(三)
原子类操作
既然强调了并发访问,那么就必须考虑操作系统位数: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<Member> 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<T>
// 抽象类AtomicLongFieldUpdater更新器
AtomicLongFieldUpdater更新器获得对象的方法:
@CallerSensitive
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
Class<?> caller = Reflection.getCallerClass();
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
return new CASUpdater<U>(tclass, fieldName, caller);
else
return new LockedUpdater<U>(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的开包里面会发现有大量的原子操作类出现。
JUC——原子类操作(三)的更多相关文章
- java 多线程系列---JUC原子类(三)之AtomicLongArray原子类
AtomicLongArray介绍和函数列表 在"Java多线程系列--“JUC原子类”02之 AtomicLong原子类"中介绍过,AtomicLong是作用是对长整形进行原子操 ...
- Java多线程系列--“JUC原子类”02之 AtomicLong原子类
概要 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.本章以AtomicLong对基本类型的原子类进行介绍.内容包括:Atomic ...
- Java多线程系列--“JUC原子类”04之 AtomicReference原子类
概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...
- Java多线程系列--“JUC原子类”05之 AtomicLongFieldUpdater原子类
概要 AtomicIntegerFieldUpdater, AtomicLongFieldUpdater和AtomicReferenceFieldUpdater这3个修改类的成员的原子类型的原理和用法 ...
- 【Java_多线程并发编程】JUC原子类——4种原子类
根据修改的数据类型,可以将JUC包中的原子操作类可以分为4种,分别是: 1. 基本类型: AtomicInteger, AtomicLong, AtomicBoolean ;2. 数组类型: Atom ...
- java多线程系类:JUC原子类:03之AtomicLongArray原子类
概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...
- Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类
概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...
- JDK原子类操作
JDK原子类操作及原理 在JDK5之后,JDK提供了对变量的原子类操作, java.util.concurrent.atomic里都是原子类 原子类的分类 原子更新基本类型 原子更新数组 原子更新抽象 ...
- 【Java_多线程并发编程】JUC原子类——原子类中的volatile变量和CAS函数
JUC中的原子类是依靠volatile变量和Unsafe类中的CAS函数实现的. 1. volatile变量的特性 内存可见性(当一个线程修改volatile变量的值后,另一个线程就可以实时看到此变量 ...
随机推荐
- Dubbo实践(三)框架设计
整体设计 图例说明: 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口: 图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层 ...
- vue项目在ie浏览器和360浏览器的兼容模式下不显示,出现promise未定义问题
出现“promise未定义”问题,因为对es6不兼容 在项目中安装 babel-polyfill 依赖包 ① npm install babel-polyfill --save-dev ② 在main ...
- 利用PDCA工具改进周例会
PDCA简介 PDCA循环又叫戴明环,是美国质量管理专家休哈特博士首先提出的,由戴明采纳.宣传,获得普及,从而也被称为“戴明环”. PDCA最早用来解决全面质量管理问题,但是PDCA也可以用来作为一个 ...
- [WCF学习笔记] 我的WCF之旅(1):创建一个简单的WCF程序
近日学习WCF,找了很多资料,终于找到了Artech这个不错的系列.希望能从中有所收获. 本文用于记录在学习和实践WCF过程中遇到的各种基础问题以及解决方法,以供日后回顾翻阅.可能这些问题都很基础,可 ...
- mysql数据库用户密码管理
创建用户:create user 'oracle'@'localhost' identified by 'password'; MySQL 8以上:alter user 'root'@'localho ...
- java 字节流文件复制方法总结
1.使用字节流每次读写单个字节 public static void main(String[] args) throws IOException { FileInputStream fis = ne ...
- Redis的特性以及优势(附官网)
NoSQL:一类新出现的数据库(not only sql) 泛指非关系型的数据库 不支持SQL语法 存储结构跟传统关系型数据库中的那种关系表完全不同,nosql中存储的数据都是KV形式 NoSQL的世 ...
- [示例] Firemonkey 面包屑导航
原码下载:[示例]Firemonkey面包屑导航_Aone.zip 效果:(以下效果不用写一行代码)
- 苹果cms网站漏洞修复解决办法
苹果cms系统,是目前很多电影网站都在使用的一套网站系统,开源,免费,扩展性较好,支持一键采集,伪静态化,高并发的同时承载,获得的很多站长的喜欢,于近日被网站安全检测发现,maccms存在网站漏洞,s ...
- 几个并发的术语解释——QPS,TPS,PV
从英文全称翻译出字面意思就OK啦! PV=page view TPS=transactions per second QPS=queries per second RPS=requests per ...