美文网首页
JUC并发编程-3.原子变量Atomic

JUC并发编程-3.原子变量Atomic

作者: 笨鸡 | 来源:发表于2019-06-19 21:17 被阅读0次

    1.先来个计数器的递增

    • UnSafeAdd.java 对线程没采取任何措施
    package com.ctgu.juc_project.example.start;
    
    import com.ctgu.juc_project.annotation.NotThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.CountDownLatch;
    
    @NotThreadSafe
    @Slf4j
    public class UnSafeAdd {
    
        private static int threadCount = 10;
        private static CountDownLatch countDown = new CountDownLatch(threadCount);
        private static int count = 0;
    
        private static void add(){
            for (int i = 0; i < 1000; i++) {
                count += 1;
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            countDown.countDown();
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < threadCount; i++) {
                new Thread(UnSafeAdd::add).start();
            }
            countDown.await();
            log.info("count: {}", count);
        }
    }
    
    • SafeAddWithSyn.java 加锁效率低下
    package com.ctgu.juc_project.example.start;
    
    import com.ctgu.juc_project.annotation.ThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.CountDownLatch;
    
    @ThreadSafe
    @Slf4j
    public class SafeAddWithSyn {
    
        private static int threadCount = 10;
        private static CountDownLatch countDown = new CountDownLatch(threadCount);
        private static int count = 0;
    
        private synchronized static void add(){
            for (int i = 0; i < 1000; i++) {
                count += 1;
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            countDown.countDown();
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < threadCount; i++) {
                new Thread(SafeAddWithSyn::add).start();
            }
            countDown.await();
            log.info("count: {}", count);
        }
    }
    
    • SafeAddWithAtomic.java 原子变量
    package com.ctgu.juc_project.example.start;
    
    import com.ctgu.juc_project.annotation.ThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.atomic.AtomicInteger;
    
    @ThreadSafe
    @Slf4j
    public class SafeAddWithAtomic {
    
        private static int threadCount = 10;
        private static CountDownLatch countDown = new CountDownLatch(threadCount);
        private static AtomicInteger count = new AtomicInteger(0);
    
        private static void add(){
            for (int i = 0; i < 1000; i++) {
                count.incrementAndGet();
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            countDown.countDown();
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < threadCount; i++) {
                new Thread(SafeAddWithAtomic::add).start();
            }
            countDown.await();
            log.info("count: {}", count.get());
        }
    }
    
    • SafeAddWithStriped64.java 类似于CurrentHashMap的atmoic分段锁
    package com.ctgu.juc_project.example.start;
    
    import com.ctgu.juc_project.annotation.ThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.atomic.LongAdder;
    
    @ThreadSafe
    @Slf4j
    public class SafeAddWithStriped64 {
    
        private static int threadCount = 10;
        private static CountDownLatch countDown = new CountDownLatch(threadCount);
        private static LongAdder count = new LongAdder();
    
        private static void add(){
            for (int i = 0; i < 1000; i++) {
                count.increment();
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            countDown.countDown();
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < threadCount; i++) {
                new Thread(SafeAddWithStriped64::add).start();
            }
            countDown.await();
            log.info("count: {}", count);
        }
    }
    

    2.原子变量数据类型

    • AtomicBoolean
    • AtomicInteger
    • AtomicLong

    CAS算法原理: CompareAndSwap(V,E,N)
    volatile V; 多线程可见,表示准备要被更新的变量
    E表示我们提供的 期望的值
    N表示新值 ,准备更新V的值

    3.原子变量分段Striped64类

    • DoubleAccumlator
    • DoubleAddr
    • LongAccumulator
    • LongAddr
    • Striped64

    分治的思想,将一个数值分成多个线程持有段Cell,然后同时CAS,最后将分段的值加和。

    4.原子变量数组类

    • AtomicIntegerArray
    • AtomicLongArray
    • AtomicReferenceArray
    package com.ctgu.juc_project.example.start;
    
    import com.ctgu.juc_project.annotation.NotThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.CountDownLatch;
    
    
    @Slf4j
    @NotThreadSafe
    public class UnSafeArray {
    
        private static int threadCount = 10;
        private static CountDownLatch countDown = new CountDownLatch(threadCount);
        private static int[] values = new int[10];
    
        private static void add(){
            for (int i = 0; i < 1000; i++) {
                for (int j = 0; j < values.length; j++) {
                    values[j]++;
                }
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            countDown.countDown();
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < threadCount; i++) {
                new Thread(UnSafeArray::add).start();
            }
            countDown.await();
            log.info("values: {}", values);
        }
    }
    
    package com.ctgu.juc_project.example.start;
    
    import com.ctgu.juc_project.annotation.ThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.atomic.AtomicIntegerArray;
    
    
    @Slf4j
    @ThreadSafe
    public class SafeArray {
    
        private static int threadCount = 10;
        private static CountDownLatch countDown = new CountDownLatch(threadCount);
        private static int[] values = new int[10];
        private static AtomicIntegerArray atomicValues = new AtomicIntegerArray(values);
    
        private static void add(){
            for (int i = 0; i < 1000; i++) {
                for (int j = 0; j < values.length; j++) {
                    atomicValues.incrementAndGet(j);
                }
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            countDown.countDown();
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < threadCount; i++) {
                new Thread(SafeArray::add).start();
            }
            countDown.await();
            log.info("atomicValues: {}", atomicValues);
            log.info("values: {}", values);
        }
    }
    

    5.原子变量引用类型

    • AtomicReference
    • AtomicMarkableReference 仅标记是否修改过,mark是boolean类型
    • AtomicStampedReference 时间戳解决ABA问题
    package com.ctgu.juc_project.example.atomic;
    
    import com.ctgu.juc_project.annotation.ThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.atomic.AtomicReference;
    
    @Slf4j
    @ThreadSafe
    public class AtomicExample4 {
    
        private static AtomicReference<Integer> count = new AtomicReference<>(0);
    
        public static void main(String[] args) {
            count.compareAndSet(0, 2); // 2
            count.compareAndSet(0, 1); // no
            count.compareAndSet(1, 3); // no
            count.compareAndSet(2, 4); // 4
            count.compareAndSet(3, 5); // no
            log.info("count:{}", count.get());
        }
    }
    

    6.原子变量字段类型

    • AtomicIntegerFieldUpdater
    • AtomicLongFieldUpdater
    • AtomicReferenceFieldUpdater
    package com.ctgu.juc_project.example.atomic;
    
    import com.ctgu.juc_project.annotation.ThreadSafe;
    import lombok.Getter;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
    
    @Slf4j
    @ThreadSafe
    public class AtomicExample5 {
    
        private static AtomicIntegerFieldUpdater<AtomicExample5> updater =
                AtomicIntegerFieldUpdater.newUpdater(AtomicExample5.class, "count");
    
        @Getter
        public volatile int count = 100;
    
        public static void main(String[] args) {
    
            AtomicExample5 example5 = new AtomicExample5();
    
            if (updater.compareAndSet(example5, 100, 120)) {
                log.info("update success 1, {}", example5.getCount());
            }
    
            if (updater.compareAndSet(example5, 100, 120)) {
                log.info("update success 2, {}", example5.getCount());
            } else {
                log.info("update failed, {}", example5.getCount());
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:JUC并发编程-3.原子变量Atomic

          本文链接:https://www.haomeiwen.com/subject/iidlqctx.html