JAVA 8 并发增强(1) 多线程修改某个计数器的方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kkgbn/article/details/52061811

Q:如何正确的并发修改一个AtomicLong的值?

		/* 不同线程检测最大值 */
		AtomicLong largest = new AtomicLong();
		long obsvValue = 0;
		/* 错误的方式,此更新不是原子性的 */
		largest.set(Math.max(largest.get(), obsvValue));
		/* 正确的方式,这种方式比锁快 */
		long oldValue;
		long newValue;
		do {
			oldValue = largest.get();
			newValue = Math.max(obsvValue, oldValue);
		} while (!largest.compareAndSet(oldValue, newValue));
		/* J8的方式 */
		largest.updateAndGet(x -> Math.max(x, obsvValue));
		/* 或者 */
		largest.accumulateAndGet(obsvValue, Math::max);

		/*
		 * 当有大量线程访问同一个原子值的时,由于乐观锁更需要太多次重试,因此会导致性能严重下降
		 * J8提供了LongAdder和LongAccumulator来解决该问题。LongAdder由多个变量组成,这些变量累加的值
		 * 就是当前值。多个线程可以更新不同的被加数
		 * ,当线程数量增加时会自动增加新的被加数。由于通常情况下都是直到所有工作完成后才需要总和值,所以这种方法效率很高
		 * 如果你的环境存在高度竞争,那就应当用LongAdder来代替AtomicLong二者之间的方法命名稍有不同
		 * 。Increment方法用来将计数器自增1,add方法用来加上某个数值,sum方法用来获取总和值
		 * tips:increment方法不会返回原始值。使用它只会抹杀掉总和值,拆分为多个被加数所带来的性能提升
		 */
		final LongAdder adder = new LongAdder();
		adder.increment();
		adder.increment();
		adder.increment();
		long total = adder.sum();
		/*
		 * LongAccumulator将这个思想带到了任意的累加操作中。在构造函数中,你需要提供操作类型及其中立元素
		 * 要与新值相加,你需要调用accumulate方法。饭后再调用get方法获取当前值。以下代码与LongAdder是一样的
		 */
		LongAccumulator adder2 = new LongAccumulator(Long::sum, 0);
		/*在某些线程中**/
		adder2.accumulate(52);


猜你喜欢

转载自blog.csdn.net/kkgbn/article/details/52061811