十、并发编程之JDK提供的原子类原理及使用

1、简介

Atomic一词跟原子有点关系,后者曾被人认为是最小物质的单位。计算机中的Atomic是指不能分割成若干部分的意思。如果一段代码被认为是Atomic,则表示这段代码在执行过程中,是不能被中断的。通常来说,原子指令由硬件提供,供软件来实现原子方法(某个线程进入该方法后,就不会被中断,直到其执行完成)

在x86 平台上,CPU提供了在指令执行期间对总线加锁的手段。CPU芯片上有一条引线#HLOCK pin,如果汇编语言的程序中在一条指令前面加上前缀”LOCK”,经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。

原子变量的原子操作也是用到了锁,只不过这个是硬件指令级别的锁,比我们软件实现的锁高效很多,更重要的是如果出现了冲突,只是不停的循环重试,而不会切换线程。如:do{ }while 循环调用一个本地方法。

2、java提供的原子类

  • 原子更新基本类型
  • 原子更新数组
  • 原子更新抽象类型
  • 原子更新字段
    在这里插入图片描述

3、原子类的使用

public class Sequence {
	// 原子性的Integer类  可以进行原子操作
	private AtomicInteger value  = new AtomicInteger(0);
	private int [] i = {2,1,4,6};
	// 原子性的Integer数组  可以进行原子操作
	private AtomicIntegerArray a = new AtomicIntegerArray(i);
	// 对普通类进行原子性引用  可以进行原子操作
	//对user的get和set方法进行原子操作,而不是对其属性
	private AtomicReference<User> user = new AtomicReference<>();
	// 对普通类的属性修改  可以进行原子操作  属性必须得用volatile修饰 public volatile int old;
	private AtomicIntegerFieldUpdater<User> old = AtomicIntegerFieldUpdater.newUpdater(User.class, "old");
	
	/**
	 *  原子操作 不会再出现线程安全问题
	 */
	public  int getNext() {
		//return value.getAndAdd(10);//value每次加10
		//return value.getAndIncrement();//value++

		//a.getAndIncrement(2);//给第2个位置的值加1
		//a.getAndAdd(2, 5);//给第2个位置的值加10

		User u = new User();
		System.out.println(old.getAndIncrement(u));
		System.out.println(old.getAndIncrement(u));
		System.out.println(old.getAndIncrement(u));
		return a.get(2);

	}

	public static void main(String[] args) {
		Sequence sequence = new Sequence();
		//第一个线程
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					System.out.println(Thread.currentThread().getName()+"      ----->"+sequence.getNext());
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
		//第二个线程
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					System.out.println(Thread.currentThread().getName()+"      ----->"+sequence.getNext());
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
		//第三个线程
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					System.out.println(Thread.currentThread().getName()+"      ----->"+sequence.getNext());
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
}

4、原理

//用其中一个方法讲解
public class AtomicInteger extends Number implements java.io.Serializable {
 	public final int updateAndGet(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();//拿到当前的值
            next = updateFunction.applyAsInt(prev);//计算下一个值
        } while (!compareAndSet(prev, next));//compareAndSet 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。这里需要注意的是这个方法的返回值实际上是是否成功修改,而与之前的值无关。
        return next;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值