AtomicInteger类详解

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);
		}
	} 
}

 可以看到执行结果,为预期的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只能在操作当中当中控制操作的原子性,只是针对于自增、自减操作;除此之外不能使线程其他地方进行同步,例如输出语句、线程的访问先后。 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值