JUC-LongAdder 冷不防 2022-09-15 06:04 152阅读 0赞 LongAdder只能用来计算加法,且从零开始计算 LongAccumulator提供了自定义的操作函数 ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16][] 普通int+sychronized、AtomicInteger和LongAdder的性能比较 public class LongAdderCalcDemo { int num = 0; public synchronized void add_synchronized() { num++; } AtomicInteger atomicInteger = new AtomicInteger(); public void add_AtomicInteger() { atomicInteger.incrementAndGet(); } LongAdder longAdder = new LongAdder(); public void add_LongAdder() { longAdder.increment(); } public static void main(String[] args) throws InterruptedException { int count = 50; int size = 1000000; LongAdderCalcDemo demo = new LongAdderCalcDemo(); CountDownLatch countDownLatch1 = new CountDownLatch(count); CountDownLatch countDownLatch2 = new CountDownLatch(count); CountDownLatch countDownLatch3 = new CountDownLatch(count); long start; long end; start = System.currentTimeMillis(); for (int i = 0; i < count; i++) { new Thread(()->{ try { for (int j = 0; j < size; j++) { demo.add_synchronized(); } } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch1.countDown(); } }).start(); } countDownLatch1.await(); end = System.currentTimeMillis(); System.out.println("add_synchronized costTime = " + (end - start) + " 毫秒, 结果 = " + demo.num); start = System.currentTimeMillis(); for (int i = 0; i < count; i++) { new Thread(()->{ try { for (int j = 0; j < size; j++) { demo.add_AtomicInteger(); } } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch2.countDown(); } }).start(); } countDownLatch2.await(); end = System.currentTimeMillis(); System.out.println("add_AtomicInteger costTime = " + (end - start) + " 毫秒, 结果 = " + demo.atomicInteger.get()); start = System.currentTimeMillis(); for (int i = 0; i < count; i++) { new Thread(()->{ try { for (int j = 0; j < size; j++) { demo.add_LongAdder(); } } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch3.countDown(); } }).start(); } countDownLatch3.await(); end = System.currentTimeMillis(); System.out.println("add_LongAdder costTime = " + (end - start) + " 毫秒, 结果 = " + demo.longAdder.sum()); } } > add\_synchronized costTime = 1880 毫秒, 结果 = 50000000 > add\_AtomicInteger costTime = 1123 毫秒, 结果 = 50000000 > add\_LongAdder costTime = 115 毫秒, 结果 = 500000 **原理** ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 1][]![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 2][] ** Striped64中有2个重要的属性,long base和Cell\[\] cells数组** ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 3][] Cell是Striped64的内部类 ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 4][] **LongAdder在无竞争的情况下,跟AtomicLong一样,对同一个base进行操作,当出现竞争关系时采用化整为零的做法,用空间换时间,****分散热点,将value值分散到一个cell数组中,不同线程会命中到数组中的不同槽中,各个线程只对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率就小很多。如果要获取真正的long值,只要将各个槽中的变量值累加返回。** **sum()会将所有cell数组中的value和base累加作为返回值,核心思想就是将之前AtomicLong一个value的更新压力分散到多个cell中去,从而降级更新热点。** ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 5][] longAdder.sum()返回当前值,在没有并发更新value的情况下,sum()会返回一个精确值,在存在并发的情况下,sum()不保证返回精确值。 **sum()执行时,并没有限制对base和cells的更新,所以LongAdder不是强一致性,它是最终一致性的。** ### 区别 ### ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 6][] ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 7][]![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 8][] [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16]: /images/20220828/c7eb86dd385844c4b447dde94f6b0838.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 1]: https://img-blog.csdnimg.cn/2021101015491972.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yqq5Yqb5aWL5paXR08=,size_20,color_FFFFFF,t_70,g_se,x_16 [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 2]: /images/20220828/90c7837d3ba44a49aeb6e6a0afd00de8.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 3]: /images/20220828/1c12d6b6bc664a5783566176f7d6bbe5.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 4]: /images/20220828/6a571a565d7c4fe0962929cbbf5b9723.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 5]: /images/20220828/744811ab33734c4b8cc78a74b3381071.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 6]: /images/20220828/53fbf52cce014277a3e0756638137a58.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 7]: https://img-blog.csdnimg.cn/2021101018420739.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yqq5Yqb5aWL5paXR08=,size_20,color_FFFFFF,t_70,g_se,x_16 [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA5Yqq5Yqb5aWL5paXR08_size_20_color_FFFFFF_t_70_g_se_x_16 8]: /images/20220828/131f6f0e4f924d55a789a6f38d9a1ef3.png
还没有评论,来说两句吧...