AtomicInteger线程安全的操作加减
参考链接:https://blog.csdn.net/z834410038/article/details/73550760
AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。
下面通过简单的例子对比来看一下 AtomicInteger 的强大的功能。
下面看一个没有做现成安全的例子:
package com;
public class AtomicIntegerTest3 {
/**
* 这里模拟一个递增的任务,开启10个线程每个线程减去10,总数为300。
* 最终结果正确是200
*/
public static void main(String[] args) throws InterruptedException {
MyThreadDemo myThreadDemo = new MyThreadDemo();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
Thread.sleep(5000);//主线程休眠5秒,得到最后结果
System.out.println("执行结果:count=" + myThreadDemo.getCount());
}
}
class MyThreadDemo implements Runnable{
private int count = 300;//初始值300,被10个线程共享
private void decrement(int i) {
count --;
System.out.println(Thread.currentThread().getName()+"执行"+i+"次,剩余count:"+count);
}
public int getCount() {
return count;
}
@Override
public void run() {
try {
Thread.sleep(100);//每个子线程进来先休眠100毫秒,模拟网络环境
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i=1;i<=10;i++) {
decrement(i);
}
}
}
可以看到结果次线程并没有预期的结果200,原因是线程不安全 。并且线程打印输出也没有顺序打印,可以看见cpu对于线程分配资源是多麽随意。
synchronized关键字实现线程同步:
package com;
public class AtomicIntegerTest3 {
/**
* 这里模拟一个递增的任务,开启10个线程每个线程减去10,总数为300。
* 最终结果正确是200
*/
public static void main(String[] args) throws InterruptedException {
MyThreadDemo myThreadDemo = new MyThreadDemo();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
Thread.sleep(5000);//主线程休眠5秒,得到最后结果
System.out.println("执行结果:count=" + myThreadDemo.getCount());
}
}
class MyThreadDemo implements Runnable{
private int count = 300;//初始值300,被10个线程共享
private synchronized void decrement(int i) {
count --;
System.out.println(Thread.currentThread().getName()+"执行"+i+"次,剩余count:"+count);
}
public int getCount() {
return count;
}
@Override
public void run() {
try {
Thread.sleep(100);//每个子线程进来先休眠100毫秒,模拟网络环境
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i=1;i<=10;i++) {
decrement(i);
}
}
}
执行结果很完美正确的,线程安全。得到预期的结果,并且由于synchronized是是在方法上,所以连输出都变得有顺序。
AtomicInteger关键字实现同步
package com;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerTest3 {
/**
* 这里模拟一个递增的任务,开启10个线程每个线程减去10,总数为300。
* 最终结果正确是200
*/
public static void main(String[] args) throws InterruptedException {
MyThreadDemo myThreadDemo = new MyThreadDemo();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
new Thread(myThreadDemo).start();
Thread.sleep(5000);//主线程休眠5秒,得到最后结果
System.out.println("执行结果:count=" + myThreadDemo.getCount());
}
}
class MyThreadDemo implements Runnable{
private AtomicInteger count = new AtomicInteger(300);//初始值300为10个线程共享
private void decrement(int i) {
count.decrementAndGet();
System.out.println(Thread.currentThread().getName()+"执行"+i+"次,剩余count:"+count.get());
}
public int getCount() {
return count.get();
}
@Override
public void run() {
try {
Thread.sleep(100);//每个子线程进来先休眠100毫秒,模拟网络环境
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i=1;i<=10;i++) {
decrement(i);
}
}
}
![](http://dl2.iteye.com/upload/attachment/0130/7975/c86f3aa5-b67a-3c7f-82dd-836155cce297.png)
可以看到执行结果,为预期的200.但是顺序不正确,但是这个是正常的。因为AtomicInteger 同步的范围指针对于这个它本身的变量去同步的。当然没有同步打印的语句了。对于数据本身来说已经做到线程安全了。
AtomicInteger 申明变量,执行count.decrementAndGet();就相当于同步代码块:
synchronized {
count -- ;
}
看到此代码块只是同步了自减操作。
AtomicInteger常用接口:
//获取当前的值
public final int get()
//取当前的值,并设置新的值
public final int getAndSet(int newValue)
//获取当前的值,并自增
public final int getAndIncrement()
//获取当前的值,并自减
public final int getAndDecrement()
//获取当前的值,并加上预期的值
public final int getAndAdd(int delta)
但是重点注意:AtomicInteger只能在操作当中当中控制操作的原子性,只是针对于自增、自减操作;除此之外不能使线程其他地方进行同步,例如输出语句、线程的访问先后。