1. Atomic

java.util.concurrent.atomic提供了一组原子类型操作。如AtomicInteger提供了

    int addAndGet(int delta)
int incrementAndGet()
int get()
int compareAndGet()

1.1 无锁线程安全

Atomic类可以实现无锁(lock-free)的线程安全(thread-safe)访问

原理:CAS(Compare and Set)如果AtomicInteger实例的值是prev,就替换为next,返回true;否则,返回false

```#java
/*
* 在这个操作中,如果AtomicInteger当前的值是prev,就更新为next,返回true,终止循环;
* 如果AtomicInteger当前的值不等于prev,就什么也不做,返回false,继续循环。
*/
public int add1AndGet(AtomicInteger var){
int prev, next;
do{
prev = var.get(); //之后其他的线程修改了prev的值,也不影响结果
next = prev + 1;
}while ( ! var.compareAndSet(prev, next));
return prev;
}
```
利用CAS操作,可以保证,即时在do while循环中,其他的线程在prev = var.get()后修改了AtomicInteger的值,最终结果也一定是正确的。
### 1.2 incrementAndGet
通常不需要直接使用do...while..来调用compileAndGet,而是用incrementAndGet()这种封装的方法。
```#java
AtomicLong var = new AtomicLong(0);
public long getNextId(){ //多线程安全的id序列生成器
return var.incrementAndGet();
}
```
## 2.示例
```#java
import java.util.concurrent.atomic.AtomicInteger;

class Counter{

private AtomicInteger value = new AtomicInteger();

//add、dec、get不再使用synchronized或ReentrantLock加锁,因为Atomic本身就是原子操作

public int add(int m){

return this.value.addAndGet(m);

}

public int dec(int m){

return this.value.addAndGet(-m);

}

public int get(){

return this.value.get();

}

}

public class Main{

final static int LOOP = 100;

public static void main(String[] args) throws InterruptedException{

Counter counter = new Counter();

Thread t1 = new Thread(){

public void run(){

for(int i=0;i<LOOP;i++) {

counter.add(1);

}

}

};

Thread t2 = new Thread(){

public void run(){

for(int i=0;i<LOOP;i++){

counter.dec(1);

}

}

};

t1.start();

t2.start();

t1.join();

t2.join();

System.out.println(counter.get());

System.out.println("END");

}

}

<img src="https://img2018.cnblogs.com/blog/1418970/201906/1418970-20190613170947374-25418412.png" width="500" />

##    3.总结:
使用java.util.atomic提供的原子操作可以简化多线程编程
* AtomicInteger/AtomicLong/AtomicArray
* 原子操作实现了无锁的线程安全
* 适用于计数器、累加器

廖雪峰Java11多线程编程-3高级concurrent包-5Atomic的更多相关文章

  1. 廖雪峰Java11多线程编程-3高级concurrent包-4Concurrent集合

    Concurrent 用ReentrantLock+Condition实现Blocking Queue. Blocking Queue:当一个线程调用getTask()时,该方法内部可能让给线程进入等 ...

  2. 廖雪峰Java11多线程编程-3高级concurrent包-1ReentrantLock

    线程同步: 是因为多线程读写竞争资源需要同步 Java语言提供了synchronized/wait/notify来实现同步 编写多线程同步很困难 所以Java提供了java.util.concurre ...

  3. 廖雪峰Java11多线程编程-3高级concurrent包-6ExecutorService

    Java语言内置多线程支持: 创建线程需要操作系统资源(线程资源,栈空间) 频繁创建和销毁线程需要消耗大量时间 如果可以复用一个线程 线程池: 线程池维护若干个线程,处于等待状态 如果有新任务,就分配 ...

  4. 廖雪峰Java11多线程编程-3高级concurrent包-9Fork_Join

    线程池可以高效执行大量小任务: Fork/Join线程池可以执行一种特殊的任务: 把一个大任务拆成多个小任务并行执行 Fork/Join是在JDK 1.7引入的 示例:计算一个大数组的和 Fork/J ...

  5. 廖雪峰Java11多线程编程-3高级concurrent包-8CompletableFuture

    使用Future可以获得异步执行结果 Future<String> future = executor.submit(task); String result = future.get() ...

  6. 廖雪峰Java11多线程编程-3高级concurrent包-7Future

    JDK提供了ExecutorService接口表示线程池,可以通过submit提交一个任务. ExecutorService executor = Executors.newFixedThreadPo ...

  7. 廖雪峰Java11多线程编程-3高级concurrent包-3Condition

    Condition实现等待和唤醒线程 java.util.locks.ReentrantLock用于替代synchronized加锁 synchronized可以使用wait和notify实现在条件不 ...

  8. 廖雪峰Java11多线程编程-3高级concurrent包-2ReadWriteLock

    ReentrantLock保证单一线程执行 ReentrantLock保证了只有一个线程可以执行临界区代码: 临界区代码:任何时候只有1个线程可以执行的代码块. 临界区指的是一个访问共用资源(例如:共 ...

  9. 廖雪峰Java11多线程编程-2线程同步-3死锁

    1.线程锁可以嵌套 在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁 Java的线程锁是可重入的锁.对同一个对象,同一个线程,可以多次获取他的锁,即同一把锁可以嵌套.如以下 ...

随机推荐

  1. linux网络速率监控

    #!/bin/bash #作者:fafu_li #时间: #监控网卡传输速率 source /etc/profile #加载系统环境变量 source $HOME/.bash_profile #加载用 ...

  2. 让BB-Black通过usb0上网

    Frm: http://blog.csdn.net/jamselaot/article/details/17080011 既然我们已经用usb0作为主机和BB-Black之间的网络通道了,再进一步,就 ...

  3. AtCoder ABC 130F Minimum Bounding Box

    题目链接:https://atcoder.jp/contests/abc130/tasks/abc130_f 题目大意 给定地图上 N 个点的坐标和移动方向,它们会以每秒 1 个单位的速度移动,设 A ...

  4. 干货:Java正确获取客户端真实IP方法整理

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...

  5. UVA 12304 /// 圆的综合题 圆的模板

    题目大意: ①给出三角形三个点,求三角形外接圆,求外接圆的圆心和半径. ②给出三角形三个点,求三角形内接圆,求内接圆的圆心和半径. ③给出一个圆,和一个点,求过该点的圆的切线与x轴的夹角(0<= ...

  6. js面向对象编程:this究竟代表什么?第二篇

         总觉得自己弄明确了js中this的含义.this总是指向调用方法的对象,作为方法调用,那么this就是指实例化的对象.但前几天自己写脚本却遇到了一个非常奇怪的问题.    代码例如以下:   ...

  7. Linux服务器下对Oracle数据库expdp(导出)和impdp(导入)

    紧接上篇文章,Oracle数据库架构已经创建完成,我的需求是:将老服务器上的数据库迁移到新的数据库上. 这就用到impdp(导入)操作. 要想实现对新数据库的impdp(导入)工作, 首先需要从老的数 ...

  8. Python 执行tail文件并操作

    def log_search(self, logfile, search_content, timeout=10): import time import subprocess import sele ...

  9. JS对象 返回/设置年份方法 get/setFullYear() 返回/设置年份,用四位数表示。.顺序格式依次为:星期、月、日、年、时、分、秒、时区。(火狐浏览器)

    返回/设置年份方法 get/setFullYear() 返回/设置年份,用四位数表示. var mydate=new Date();//当前时间2014年3月6日 document.write(myd ...

  10. thinkphp action参数绑定

    参数绑定是通过直接绑定URL地址中的变量作为操作方法的参数,可以简化方法的定义甚至路由的解析. 参数绑定功能默认是开启的,其原理是把URL中的参数(不包括模块.控制器和操作名)和操作方法中的参数进行绑 ...