【Java多线程】Java 原子操作类API(以AtomicInteger为例)
1、java.util.concurrent.atomic 的包里有AtomicBoolean, AtomicInteger,AtomicLong,AtomicLongArray,
AtomicReference等原子类的类,主要用于在高并发环境下的高效程序处理,来帮助我们简化同步处理.
在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。
2、AtomicInteger的基本方法
- 从AtomicInteger获取值
System.out.println(atomicInteger.get());
--->输出 : 123
- 创建一个不传值的,默认值为0
AtomicInteger atomicInteger = new AtomicInteger();
System.out.println(atomicInteger.get());
---->输出: 0
- 获取和赋值
atomicInteger.get(); //获取当前值
atomicInteger.set(999); //设置当前值
- atomicInteger.compareAndSet(expectedValue,newValue)
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(0);
System.out.println(atomicInteger.get());
int expectedValue = 123;
int newValue = 234;
Boolean b =atomicInteger.compareAndSet(expectedValue, newValue);
System.out.println(b);
System.out.println(atomicInteger);
}
----》输出结果为: 0 false 0
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(123);
System.out.println(atomicInteger.get());
int expectedValue = 123;
int newValue = 234;
Boolean b =atomicInteger.compareAndSet(expectedValue, newValue);
System.out.println(b);
System.out.println(atomicInteger);
}
-----》输出结果为: 123 true 234
由上可知该方法表示,atomicInteger的值与expectedValue相比较,如果不相等,则返回false,
atomicInteger原有值保持不变;如果两者相等,则返回true,atomicInteger的值更新为newValue
- getAndAdd()方法与AddAndGet方法
AtomicInteger atomicInteger = new AtomicInteger(123);
System.out.println(atomicInteger.get()); --123
System.out.println(atomicInteger.getAndAdd(10)); --123 获取当前值,并加10
System.out.println(atomicInteger.get()); --133
System.out.println(atomicInteger.addAndGet(10)); --143 获取加10后的值,先加10
System.out.println(atomicInteger.get()); --143
- getAndDecrement()和DecrementAndGet()方法
AtomicInteger atomicInteger = new AtomicInteger(123);
System.out.println(atomicInteger.get()); --123
System.out.println(atomicInteger.getAndDecrement()); --123 获取当前值并自减
System.out.println(atomicInteger.get()); --122
System.out.println(atomicInteger.decrementAndGet()); --121 先自减再获取减1后的值
System.out.println(atomicInteger.get()); --121
3、使用AtomicInteger,即使不用同步块synchronized,最后的结果也是100,可用看出AtomicInteger的作用,用原子方式更新的int值。主要用于在高并发环境下的高效程序处理。使用非阻塞算法来实现并发控制。
public class Counter {
public static AtomicInteger count = new AtomicInteger(0);
public static void inc(){
try{
Thread.sleep(1); //延迟1毫秒
}catch (InterruptedException e){ //catch住中断异常,防止程序中断
e.printStackTrace();
}
count.getAndIncrement();//count值自加1
}
public static void main(String[] args) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(100);
for(int i=0;i<100;i++){
new Thread(new Runnable() {
@Override
public void run() {
Counter.inc();
latch.countDown();
}
}).start();
}
latch.await();
System.out.println("运行结果:"+Counter.count);
}
}
运行结果: 100
4、使用普通Integer
public class Counter {
public volatile static int count = 0;
public static void inc(){
try{
Thread.sleep(1); //延迟1毫秒
}catch (InterruptedException e){ //catch住中断异常,防止程序中断
e.printStackTrace();
}
count++;//count值自加1
}
public static void main(String[] args) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(100);
for(int i=0;i<100;i++){
new Thread(new Runnable() {
@Override
public void run() {
Counter.inc();
latch.countDown();
}
}).start();
}
latch.await();
System.out.println("运行结果:"+Counter.count);
}
}
运行结果:98
5、如果在inc方法前面加个synchronized也能是线程安全的;
它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
import java.util.concurrent.CountDownLatch;
/**
* created by guanguan on 2017/10/23
**/
public class Counter {
public volatile static Integer count = 0;
public synchronized static void inc(){
try{
Thread.sleep(1); //延迟1毫秒
}catch (InterruptedException e){ //catch住中断异常,防止程序中断
e.printStackTrace();
}
count++;//count值自加1
}
public static void main(String[] args) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(100);
for(int i=0;i<100;i++){
new Thread(new Runnable() {
@Override
public void run() {
Counter.inc();
latch.countDown();
}
}).start();
}
latch.await();
System.out.println("运行结果:"+Counter.count);
}
}
运行结果:100
synchronized的使用说明:
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
6、从上面的例子中我们可以看出:使用AtomicInteger是非常的安全的.而且因为AtomicInteger由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快。
java的关键域有3个
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
private volatile int value;
这里, unsafe是java提供的获得对对象内存地址访问的类,注释已经清楚的写出了,它的作用就是在更新操作时提供“比较并替换”的作用。实际上就是AtomicInteger中的一个工具。
valueOffset是用来记录value本身在内存的便宜地址的,这个记录,也主要是为了在更新操作在内存中找到value的位置,方便比较。
注意:value是用来存储整数的时间变量,这里被声明为volatile,就是为了保证在更新操作时,当前线程可以拿到value最新的值(并发环境下,value可能已经被其他线程更新了)。
这里,我们以自增的代码为例,可以看到这个并发控制的核心算法:
源码
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
}
【Java多线程】Java 原子操作类API(以AtomicInteger为例)的更多相关文章
- Java多线程之原子操作类
在并发编程中很容易出现并发安全问题,最简单的例子就是多线程更新变量i=1,多个线程执行i++操作,就有可能获取不到正确的值,而这个问题,最常用的方法是通过Synchronized进行控制来达到线程安全 ...
- java中的原子操作类AtomicInteger及其实现原理
/** * 一,AtomicInteger 是如何实现原子操作的呢? * * 我们先来看一下getAndIncrement的源代码: * public final int getAndIncremen ...
- Java多线程并发工具类-信号量Semaphore对象讲解
Java多线程并发工具类-Semaphore对象讲解 通过前面的学习,我们已经知道了Java多线程并发场景中使用比较多的两个工具类:做加法的CycliBarrier对象以及做减法的CountDownL ...
- Java中的原子操作类
转载: <ava并发编程的艺术>第7章 当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可 ...
- Java并发之原子操作类汇总
当程序更新一个变量时,如果是多线程同时更新这个变量,可能得到的结果与期望值不同.比如:有一个变量i,A线程执行i+1,B线程也执行i+1,经过两个线程的操作后,变量i的值可能不是期望的3,而是2.这是 ...
- Java多线程01(Thread类、线程创建、线程池)
Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...
- 【Java并发】Java中的原子操作类
综述 JDK从1.5开始提供了java.util.concurrent.atomic包. 通过包中的原子操作类能够线程安全地更新一个变量. 包含4种类型的原子更新方式:基本类型.数组.引用.对象中字段 ...
- Java多线程基础——Lock类
之前已经说道,JVM提供了synchronized关键字来实现对变量的同步访问以及用wait和notify来实现线程间通信.在jdk1.5以后,JAVA提供了Lock类来实现和synchronized ...
- Java多线程同步工具类之CountDownLatch
在过去我们实现多线程同步的代码中,往往使用join().wait().notiyAll()等线程间通信的方式,随着JUC包的不断的完善,java为我们提供了丰富同步工具类,官方也鼓励我们使用工具类来实 ...
- (转)java 多线程 对象锁&类锁
转自:http://blog.csdn.net/u013142781/article/details/51697672 最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不 ...
随机推荐
- 带你理解MST性质
写在前面 最小生成树的引出 假设要在n个城市之间建立通信联络网,则连通n个城市需要n-1条线路.在这种情况下,我们自然需要考虑一个问题,如何在最节省经费的条件下建立这个网络? 很自然地我们会想到,将各 ...
- storm调用kafka重复消费的问题
1. 实现IBolt接口的bolt需要显式调用collector.ack(); 2. 继承自BaseBasicBlot的bolt, 会帮你自动调用ack的
- 如何系统学习C 语言(中)之 联合体、枚举篇
在C语言中有一个和结构体非常像的数据类型,它的名字叫做联合体,也被称为共用体或公用体. 1,联合体 1,联合体的定义 定义联合体需要使用"union" 关键字,格式如下: unio ...
- Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create()
在Java中处理JSON格式的数据时,Google Gson 是个不错的选择,用起来挺方便的,也有一定灵活性.我现在工作中在参与的两个项目里都有用它.不过它在处理Date格式时有个小陷阱,在不同环境 ...
- 尖端之作看逐浪-Zoomla!逐浪CMS python版发布
免费下载:https://www.z01.com/down/3723.shtml Python是跻身于当代IT世界最流行和代码最高效的编程语言之一. 带着对技术的卓越追求.对客户的承诺.对品质的极致追 ...
- 菜鸡的Java笔记 第二十七 - java 链表基本概念
链表基本概念 1.链表的基本形式 2.单向链表的完整实现 认识链表 链表= 可变长的对象数组,属于动态对象数组的范畴 链表 ...
- DECODE 与CASE WHEN 的比较
1.DECODE 只有Oracle 才有,其它数据库不支持; 2.CASE WHEN的用法, Oracle.SQL Server. MySQL 都支持; 3.DECODE 只能用做相等判断,但是可以配 ...
- 力扣 - 剑指 Offer 27. 二叉树的镜像
题目 剑指 Offer 27. 二叉树的镜像 思路1(递归) 我们可以使用深度优先搜索,先递归到链表的末尾,然后从末尾开始两两交换.就相当于后续遍历而已 记得要先保存下来node.right节点,因为 ...
- CSS-sprit 雪碧图
CSS-sprit 雪碧图 可以将 多个小图片统一保存到一个大图片中,然后通过调整background-position来显示响应的图片 这样图片会同时加载到网页中 就可以避免出现闪烁 ...
- 痞子衡嵌入式:深扒IAR启动函数流程之段初始化函数__iar_data_init3实现
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR启动函数流程里的段初始化函数__iar_data_init3实现. 本篇是 <IAR启动函数流程及其__low_level_ ...