java核心-多线程(8)- 并发原子类
使用锁能解决并发时线程安全性,但锁的代价比较大,而且降低性能。有些时候可以使用原子类(juc-atomic包中的原子类)。还有一些其他的非加锁式并发处理方式,我写这篇文章来源于Java中有哪些无锁技术来解决并发问题的思考。
1.原子类场景
刚才说了,原子类是在不加锁的情况下,实现并发安全。我们知道锁synchronized/lock能实现并发安全的三点要求:原子性、可见性和有序性。而原子类顾名思义可以保证原则性其他两点不能确定(我是边想边写的,后面我会给出结论)。
好吧,写不下去了,还是看看现成的总结吧。百度收索“Java原子类使用场景”,随便点开两个,基本上都是通过举了一个“多线程计数”的例子来说明使用场景+底层使用CAS来总结原理。好了这里我就得出结论原子类使用场景之一多线程计数器的实现。后面如果找到更好的总结再补充。
这里说一句废话,看似我在写一些没有用心总结的东西,也不会有人看,网上这样的文章一堆,我干嘛要写呢,我告诉你,我主要是形成自己关于这块的知识的痕迹,写的虽然不怎么的,但至少我也是按结构,经过思考过的输出产品。这一系列的文章最终能搭建我的知识体系,知识体系一旦搭建完成,就能建立知识地图,快速反应和检索,思考和工作效率得到提升。我深信这一点。
#####2.原子类分类
```
分类这块看到一个比较好的总结,[Java16个原子类介绍-基于JDK8](https://blog.csdn.net/weixin_38003389/article/details/88569336),讲的很全面,每个都有例子说明
总结一下:
1.jdk8之前共12个,jdk8新增了4个
2.具体分类
a.原子基本类型:AtomicInteger、AtomicBoolean、AtomicLong
b.原子数组(通过原子操作的方式更新数组中元素):AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
c.原子引用类型:AtomicRerence、AtomicMarkableReference
d.原子字段类(通过原子操作更新某个类的字段):AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedFieldUpdater、AtomicReferenceFieldUpdater
e.jdk8新增:DoubleAccumulator、LongAccumulator、DoubleAdder、LongAdder
3.具体使用注意
a.要想使用原子字段类需要两步。第一步,因为原子更新字段类都是抽象类,每次使用的时候必须使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新的类和属性。第二步,更新类的字段必须使用 public volatile 修饰。
<br>
#####3.原子类实现原理
a.大多数使用Unsafe类的CAS原子指令。
b.jdk8新增的LongAdder使用的不是Unsafe的CAS原理,而是类似的思想,下图很好的说明了这种思想。LongAdder不可以代替AtomicLong ,虽然 LongAdder 的 add() 方法可以原子性操作,但是并没有使用 Unsafe 的CAS算法,只是使用了CAS的思想。

如图LongAdder则是内部维护多个变量,每个变量初始化都0,在同等并发量的情况下,争夺单个变量的线程量会减少这是变相的减少了争夺共享资源的并发量,另外多个线程在争夺同一个原子变量时候如果失败并不是自旋CAS重试,而是尝试获取其他原子变量的锁,最后获取当前值时候是把所有变量的值累加后返回的(不一定准确,没有并发情况下真实)。
<br>
#####4.原子类使用demo
public class TestAtomicInteger {
static Integer count = 0;
public static void main(String[] args){
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
count++;
}
System.out.println("thread1 count add 100000 over");
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
count++;
}
System.out.println("thread2 count add 100000 over");
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("最终:"+count);
}
}
//该例子输出的结果并不是200000,而是小于它,只需要把count的类型改为AtomicInteger即可(前面不需要加volatile关键字)。
java核心-多线程(8)- 并发原子类的更多相关文章
- Java多线程系列--“JUC原子类”02之 AtomicLong原子类
概要 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.本章以AtomicLong对基本类型的原子类进行介绍.内容包括:Atomic ...
- Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类
概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...
- Java多线程系列--“JUC原子类”04之 AtomicReference原子类
概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...
- Java多线程系列--“JUC原子类”05之 AtomicLongFieldUpdater原子类
概要 AtomicIntegerFieldUpdater, AtomicLongFieldUpdater和AtomicReferenceFieldUpdater这3个修改类的成员的原子类型的原理和用法 ...
- java 多线程系列---JUC原子类(三)之AtomicLongArray原子类
AtomicLongArray介绍和函数列表 在"Java多线程系列--“JUC原子类”02之 AtomicLong原子类"中介绍过,AtomicLong是作用是对长整形进行原子操 ...
- java并发:原子类之AtomicLong
原子类之AtomicLong java线程中的操作,需要满足原子性.可见性等原则,比如i++这样的操作不具备原子性, A线程读取了i,另一个线程执行i++,A线程再执行i++就会引发线程安全问题 推荐 ...
- java核心-多线程(1)-知识大纲
Thread,整理一份多线程知识大纲,大写意 1.概念介绍 线程 进程 并发 2.基础知识介绍 Java线程类 Thread 静态方法&实例方法 Runnable Callable Futur ...
- Java并发—原子类,java.util.concurrent.atomic包(转载)
原子类 Java从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中 的原子操作类提供了一种用法简单.性能高效.线程安全地更新一个变量 ...
- java 多线程系列---JUC原子类(二)之AtomicLong原子类
概要 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.本章以AtomicLong对基本类型的原子类进行介绍. AtomicLong ...
随机推荐
- Java基础 -4.2
Switch分支语句 switch是一个开关语句,它主要是根据内容来进行判断的,需要注意的是switch中可以判断的只能够是数据(int.char.枚举.String)而不能够使用逻辑判断 publi ...
- LeetCode 345. Reverse Vowels of a String(双指针)
题意:给定一个字符串,反转字符串中的元音字母. 例如: Input: "leetcode" Output: "leotcede" 法一:双指针 class So ...
- linux 部署java 项目命令
1:服务器部署路径:/home/tomcat/tomcat/webapps (用FTP工具链接服务器把包上传到此目录) 2:进入项目文件夹 cd /home/tomcat/tomcat/webapp ...
- Windows 控制台命令笔记
1. cmd中输出中文乱码问题: CHCP是一个计算机指令,能够显示或设置活动代码页编号. C:\windows\system32>CHCP 活动代码页: 936 原因是我们使用了GBK编码,下 ...
- 虚拟机centos7 识别不出网卡的解决方案
问题提出 之前在VMware安装centos 7(网络连接采取Nat方式),进入Centos 7后成功开启了sshd服务,然后在主机(我的windows系统)用puTTY软件可以ssh到虚拟机上.后来 ...
- etc/passwd 和 /etc/shadow 文件内容及其解释
/etc/passwd 和 /etc/shadow 文件内容及其解释 默认情况下,/etc/passwd 存储有关本地用户的信息 /etc/passwd 采用以下格式: 1)username ...
- Linux CentOS7 VMware linux和windows互传文件、用户配置文件和密码配置文件、用户组管理、用户管理
一. linux和windows互传文件 X-shell.Securecrt远程终端,与Windows之间互传文件. 安装一个工具lrzsz [root@davery ~]# yum install ...
- SpringBoot集成百度UEditor图片上传后直接访问404解决办法
SpringBoot项目上传图片一般是上传至远程服务器存储,开发过程中可能会上传至当前项目的某个静态目录中,此时就会遇到这个问题,文件在上传之后直接访问并不能被访问到,必须重新加载项目. 首先分析一下 ...
- BOM--location对象、history对象
location对象 location 是最有用的BOM 对象之一,它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能. 事实上,location 对象是很特别的一个对象,因为它既是win ...
- 时间转换(scanf的指定格式读入)
给定一个12小时制的时间,请将其转换成24小时制的时间.说明:12小时制的午夜12:00:00AM,对应的24小时制时间为00:00:00.12小时制的中午12:00:00PM,对应的24小时制时间为 ...