使用锁能解决并发时线程安全性,但锁的代价比较大,而且降低性能。有些时候可以使用原子类(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的思想。
![](https://img2018.cnblogs.com/blog/1012214/202001/1012214-20200122180604029-714306250.jpg)
如图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)- 并发原子类的更多相关文章

  1. Java多线程系列--“JUC原子类”02之 AtomicLong原子类

    概要 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.本章以AtomicLong对基本类型的原子类进行介绍.内容包括:Atomic ...

  2. Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类

    概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...

  3. Java多线程系列--“JUC原子类”04之 AtomicReference原子类

    概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...

  4. Java多线程系列--“JUC原子类”05之 AtomicLongFieldUpdater原子类

    概要 AtomicIntegerFieldUpdater, AtomicLongFieldUpdater和AtomicReferenceFieldUpdater这3个修改类的成员的原子类型的原理和用法 ...

  5. java 多线程系列---JUC原子类(三)之AtomicLongArray原子类

    AtomicLongArray介绍和函数列表 在"Java多线程系列--“JUC原子类”02之 AtomicLong原子类"中介绍过,AtomicLong是作用是对长整形进行原子操 ...

  6. java并发:原子类之AtomicLong

    原子类之AtomicLong java线程中的操作,需要满足原子性.可见性等原则,比如i++这样的操作不具备原子性, A线程读取了i,另一个线程执行i++,A线程再执行i++就会引发线程安全问题 推荐 ...

  7. java核心-多线程(1)-知识大纲

    Thread,整理一份多线程知识大纲,大写意 1.概念介绍 线程 进程 并发 2.基础知识介绍 Java线程类 Thread 静态方法&实例方法 Runnable Callable Futur ...

  8. Java并发—原子类,java.util.concurrent.atomic包(转载)

    原子类 Java从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中 的原子操作类提供了一种用法简单.性能高效.线程安全地更新一个变量 ...

  9. java 多线程系列---JUC原子类(二)之AtomicLong原子类

    概要 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.本章以AtomicLong对基本类型的原子类进行介绍. AtomicLong ...

随机推荐

  1. 「快学springboot」集成Spring Security实现鉴权功能

    Spring Security介绍 Spring Security是Spring全家桶中的处理身份和权限问题的一员.Spring Security可以根据使用者的需要定制相关的角色身份和身份所具有的权 ...

  2. [转]Shell编程

    原文链接 Shell编程其实真的很简单(一) 如今,不会Linux的程序员都不意思说自己是程序员,而不会shell编程就不能说自己会Linux.说起来似乎shell编程很屌啊,然而不用担心,其实she ...

  3. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定文本左对齐

    <!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...

  4. python字典中值为列表或字典的构造方式

    1.值为列表的构造方法 dic = {} dic.setdefault(key,[]).append(value) >>dic.setdefault('a',[]).append(1) & ...

  5. Laravel 验证 教程

    英文源文章: https://www.techiediaries.com/laravel-authentication-tutorial/ 在上一篇教程中,我们已经接触过Laravel,同时介绍了最新 ...

  6. c++将字符转换成字符串

    转载:https://blog.csdn.net/dididisailor/article/details/83189135 char c; string str; stringstream stre ...

  7. JS事件委托或者事件代理原理以及实现

    事件委托(事件代理)原理:简单的说就是将事件交由别人来执行,就是将子元素的事件通过冒泡的形式交由父元素来执行. 为什么要用时间委托? 在JavaScript中,添加到页面上的事件处理程序数量将直接关系 ...

  8. Linux系统下安装python3.7.3环境

    这里用到的Linux系统是centos7系统,centos7是自带py的但是py的2.7.5版本 连接服务器的使用的是SSH Secure shell 1.首先安装依赖包 1)安装gcc编译器 gcc ...

  9. Linux centosVMware Nginx访问日志、Nginx日志切割、静态文件不记录日志和过期时间

    一.Nginx访问日志 vim /usr/local/nginx/conf/nginx.conf //搜索log_format  日至格式 改为davery格式 $remote_addr  客户端IP ...

  10. Oracle常用命令复习(备考资料)

    Oracle期末考试复习资料,大概的总结了常用的命令,不包括基础理论知识,有的不太考的东西没有整理.资料整理是在有道云笔记里完成的,在这里重新编辑太麻烦了,就附个链接了. 文档:Oracle命令复习2 ...