AtomicInteger的基本用法
1、AtomicInteger的常用方法
i++和++i不是线程安全的,因此在高并发的情况下,需要使用synchronized等关键字来保证线程安全,但是AtomicInteger
这个类则是线程安全的
public static void main(String[] args) {
AtomicInteger int1=new AtomicInteger();
System.out.println("AtomicInteger的默认值为:"+int1);
//对数据赋值
int1.set(123);
//获取数据值
System.out.println("获取数据的值为: "+int1.get());
//先相加,再获取值
System.out.println("先与12相加,再获取值: "+int1.addAndGet(12));
//先获取值,再相加
System.out.println("先获取值,再与12相加: "+int1.getAndAdd(12));
//先获取值,再赋新值
System.out.println("先获取值,再赋新值100: "+int1.getAndSet(100));
//自减1,再获取值
System.out.println("自减1,再获取值: "+int1.decrementAndGet());
//自增1,再获取值
System.out.println("自增1,再获取值: "+int1.incrementAndGet());
//先获取值,再自减1
System.out.println("先获取值,再自减1: "+int1.getAndDecrement());
//先获取值,再自增1
System.out.println("先获取值,再自增1: "+int1.getAndIncrement());
}
运行结果:
AtomicInteger的默认值为:0
获取数据的值为: 123
先与12相加,再获取值: 135
先获取值,再与12相加: 135
先获取值,再赋新值100: 147
自减1,再获取值: 99
自增1,再获取值: 100
先获取值,再自减1: 100
先获取值,再自增1: 99
2、boolean compareAndSet(int expect, int update)
示例1:
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(100);
System.out.println("变量的初始值:"+atomicInteger.get());
int expectedValue = 123;
int newValue = 234;
Boolean b =atomicInteger.compareAndSet(expectedValue, newValue);
System.out.println("执行compareAndSet后返回的bool值:"+b);
System.out.println("执行compareAndSet后变量的值:"+atomicInteger);
}
运行结果:
变量的初始值:100
执行compareAndSet后返回的bool值:false
执行compareAndSet后变量的值:100
示例2:
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("执行compareAndSet后返回的bool值:"+b);
System.out.println("执行compareAndSet后变量的值:"+atomicInteger);
}
运行结果:
变量的初始值:123
执行compareAndSet后返回的bool值:true
执行compareAndSet后变量的值:234
由示例1和示例2比较可以得到如下结论:atomicInteger
变量调用compareAndSet(int expect, int update)
方法时,
-
如果
atomicInteger
变量的值与expect
相等,则返回true,并且将update
赋值给atomicInteger
变量 -
如果
atomicInteger
变量的值与expect
不相等,则返回false,并且atomicInteger
变量保持原值不变
3、使用AtomicInteger和int在高并发下的线程安全
public class Counter {
public static AtomicInteger count=new AtomicInteger();
public volatile static int countInt=0;
public static void increase(){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
countInt++;
count.getAndIncrement(); //自增
}
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.increase();
latch.countDown();
}
}).start();
}
latch.await();
System.out.println("运行结果:count: "+Counter.count+",countInt: "+countInt);
}
}
运行结果:
运行结果:count: 100,countInt: 99
使用AtomicInteger
,即使不用同步锁synchronized
,最后的结果也是100,可用看出AtomicInteger的作用,用原子方式更新的int值。主要用于在高并发环境下的高效程序处理。使用非阻塞算法来实现并发控制。
总结:
使用AtomicInteger
是线程安全的,即使不使用synchronized关键字也能保证其是线程安全的。而且由于AtomicInteger
由硬件提供原子操作指令实现,在非激烈竞争的情况下,开销更小,速度更快