铁锤的IT奇妙探险 Java Back-End Coder

JUC原子类


JUC原子类保证了对于添加、递增等可以进行原子性操作,用于并发编程中保证线程安全。

JUC原子类

优势

原子类的作用和锁类似,用于保证并发情况下线程安全,相比于锁,有一定的优势。

  1. 粒度更细:原子变量可以把竞争范围缩小到变量级别
  2. 效率更高:除了高度竞争的情况之外,使用原子类的效率通常会比使用同步互斥锁的效率更高,因为原子类底层利用了 CAS 操作,不会阻塞线程。

6大原子类

Atomic*基本类型原子类

包括三种,分别是 AtomicIntegerAtomicLongAtomicBoolean。AtomicInteger。AtomicInteger是对int类型的封装,并且提供了原子性的访问和更新。因此需要一个用在并发场景下的整型变量时,可以直接使用它。

常用方法
public final int get() //获取当前的值
public final int getAndIncrement() //获取当前的值,并自增
public final int getAndDecrement() //获取当前的值,并自减
public final int getAndAdd(int delta) //获取当前的值,并加上预期的值
boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值,则以原子方式将该值更新为输入值(update)
存在的问题

现假设场景为:添加一个自增一次的任务,执行100次

AtomicLong中,用来保存数值的value属性被volatile修饰,需要保证自身可见性。即每次数值有变化就要进行flush和reflush,才能保证其他线程感知到数值的变化。竞争激烈时,这两步操作会耗费大量资源。

改进

在 JDK 8 中又新增了 LongAdder 这个类,这是一个针对 Long 类型的操作工具类。

/**
* 描述:     在16个线程下使用LongAdder
*/
public class LongAdderDemo { 
	public static void main(String[] args	 throws InterruptedException {
	//AtomicLong counter = new AtomicLong(0);		
	LongAdder counter = new LongAdder();	
	ExecutorService service = Executors.newFixedThreadPool(16);
	for (int i = 0; i < 100; i++) {
		service.submit(new Task(counter));
	}
	Thread.sleep(2000);
	//System.out.println(counter.get())
	System.out.println(counter.sum());
}
	static class Task implements Runnable {
	 		//private final AtomicLong counter;
		private final LongAdder counte;	
		public Task(LongAdder counter) {
			this.counter = counter;
		
		@Override
		public void run()			//counter.incrementAndGet();
		    counter.increment();
		}
	}
}

  • LongAdder引入了分段累加的概念,内部一共有两个参数参与计数:第一个叫作base,它是一个变量,第二个是Cell[ ],是一个数组。其中的base是用在竞争不激烈的情况下的,可以直接把累加结果改到base变量上。一旦竞争激烈,各个线程会分散累加到自己所对应的那个Cell[]数组的某一个对象中,而不会大家共用同一个,本质是通过空间换时间 降低冲突的概率。
  • 最后一步的求和sum方法,执行LongAdder.sum()的时候,会把各个线程里的Cell累计求和,并加上base,形成最终的总和。

Array数组类型原子类

数组里的元素,都可以保证其原子性,一共分为三种:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray。

引用类型原子类

AtomicReference引用类型原子类,AtomicReference 可以让一个对象保证原子性。

原子更新器

使用原子更新器可以将已经声明的变量进行升级,使其具有原子性。

  • AtomicIntegerFieldUpdater:原子更新整形的更新器;
  • AtomicLongFieldUpdater:原子更新长整形的更新器;
  • AtomicReferenceFieldUpdater:原子更新引用的更新器。

Adder 加法器

Accumulator 积累器

AtomicInteger和synchronized

区别

  1. 原理不同:synchronized利用的是monitor锁,原子类利用的是CAS操作保证线程安全;
  2. 使用范围不同:原子类仅仅是一个对象,而synchronized可以修饰方法,也可以修饰代码块;
  3. 粒度不同:原子类的粒度更小;
  4. 性能:synchronized是悲观锁,原子类是乐观锁,悲观锁的开销是固定的,乐观锁的开销是逐步增长的。

Similar Posts

下一篇 Seatmath

Comments