【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同步块,不 ...
随机推荐
- 【GIS】GeoServer服务Authkey配置记录
特别感谢:https://www.cnblogs.com/HandyLi/p/8624507.html 1.服务受控配置 2.授权方式 3.Url模式配置 4.Authkey密钥配置 5.使用 在wm ...
- USB3.0 转USB3.0
前段时间因为项目需求需要将相机的USB3.0口转接出来,心想那还不想简单,结果第一次就碰壁了:先说一下usb3.0的引脚定义如图: 九个脚,2个地:注意USB3.0转3.0时数据线全交叉,DM-和DP ...
- 在cmd中使用vim编译器
下载地址:http://www.vim.org/download.php#pc 下载GVIM,配置下path环境变量就可以在cmd中使用vim了 把vim.exe复制一份,更名为vi.exe,就可以直 ...
- [loj3504]支配
令$S_{x}$表示$x$支配的节点集合,可以暴力枚举$x$并求出$S_{x}$(删去$x$后从1开始dfs,复杂度为$o(nm)$),进而反过来即可求出受支配集$D_{x}$ 结论1:若$z\in ...
- 小程序嵌套H5的方式和技巧(一)
文章内多次使用了关键字"壳",首先先解释一下什么是壳 壳: 小程序由原生的web-view组件形成的页面,页面只包含技术逻辑(如打开H5页面),不包含具体业务接口请求和业务逻辑处理 ...
- 【IDEA】头注释和方法注释
头注释和方法注释 2020-09-08 10:16:17 by冲冲 1.头注释 ①设置 ②模板内容 /** * @ClassName ${NAME} * @Description ${DESCRI ...
- .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。
EF是微软.NET平台官方的ORM(objet-relation mapping),就是一种对象-关系 映射,是将关系数据库种的业务数据用对象的形式表现出来,并通过面向对象的方式讲这些对象组织起来,实 ...
- ROS机器人开发实践1->SSH远程登录要点记录
1.有线网卡 设置 找到有线网络,点击设置,修改其中的IPv4的地址和子网掩码. 1 //地址 2 192.168.xxx.xxx 3 //子网掩码 4 255.255.255.0 点击应用 2.配置 ...
- Codeforces 446C - DZY Loves Fibonacci Numbers(斐波那契数列+线段树)
Codeforces 题目传送门 & 洛谷题目传送门 你可能会疑惑我为什么要写 *2400 的题的题解 首先一个很明显的想法是,看到斐波那契数列和 \(10^9+9\) 就想到通项公式,\(F ...
- Matlab流体后处理中的奇淫巧术总结
Matlab流体后处理中的奇淫巧术总结 主要参考\demos\volvec.m示例 1.等值面绘制 %% Isosurface of MRI Data cla load mri D = squeeze ...