美文网首页
并发编程之原子变量AtomicInteger详细解析

并发编程之原子变量AtomicInteger详细解析

作者: 攻城狮Chova | 来源:发表于2021-09-05 23:36 被阅读0次
    原子变量

    AtomicInteger基本概念

    • AtomicInteger:
      • 是一个提供原子操作的Integer类
      • 通过线程安全的方式操作加减
    • AtomicInteger使用场景: AtomicInteger提供原子操作来进行Integer的使用,适合高并发的场景

    Integer与AtomicInteger的比较

    • 在使用Integer的时候,必须加上synchronized锁来保证出现并发线程同时访问的情况
    public class IntegerSample {
        private static Integer count = 0;
    
        synchronized static void increment() {
            count++;
        }
    }
    
    • AtomicInteger中不需要加锁,因为AtomicInteger是提供原子操作
    public class AtomicIntegerSample {
        private static AtomicInteger count = new AtomicInteger(0);
            
        static void increment() {
            count.getAndIncrement();
        } 
    }
    

    AtomicInteger源码

    public class AtomicInteger extends Number implements java.io.Serializable {
        private static final serialVersionUID = 6214790243416807050L;
    
        // setup to use Unsafe.compareAndSwapInt for updates
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        private static final long valueoffset;
    
        static {
            try {
                valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
            } catch (Exception e) {
                throw new Error(ex);
            }
        }
    
        private volatile int value;
    
        ...
    }
    
    • value:
      • 这里的value使用了volatile关键字
    • volatile作用: 使得多个线程可以共享变量
    • volatile的问题: 使用volatile将使得JVM优化失去作用,导致效率降低

    AtomicInteger使用实例

    • 在多线程的情况下,使用AtomicInteger:
    public class AtomicTest {
        static long randomTime() {
            return (long)(Math.random() * 1000);
        }
    
        public static void main(String args[]) {
            // 阻塞队列
            final BlockingQueue<File> queue = new LinkedBlockingQueue<File>(100);
            // 线程池
            final ExecutorService exec = Executors.newFixedThreadPool(5);
            final File root = new File("D:\\chova");
            // 完成标志
            final File exitFile = new File("");
            /*
             * 原子整型 AtomicInteger
             * AtomicInteger可以在并发的情况下达到原子化更新,避免使用了synchronized,而且性能非常高
             */
             // 读 个数
             final AtomicInteger rc = new AtomicInteger();
             // 写 个数
             final AtomicInteger wc = new AtomicInteger();
             // 读线程
             Runnable read = new Runnable() {
                public void run() {
                    scanFile(root);
                    scanFile(exitFile);
                }
        
                public void scanFile(File file) {
                    if (file.isDirectory()) {
                        File[] files = file.listFiles(new FileFilter() {
                            public boolean accept(File pathname) {
                                return pathname.isDirectory || pathname.getPath().endsWith(".java");
                            }
                        });
                        for (File one : files) {
                            scanFile(one);
                        }
                    } else {
                        try {
                            // 调用AtomicInteger的incrementAndGet(),以原子方式将当前值加1并返回新值
                            int index = rc.incrementAndGet();
                            System.out.println("Read:" + index + " " + file.getPath());
                            // 添加到阻塞队列
                            queue.put(file);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
             };
             // submit方法提交一个Runnable任务用于执行,并返回一个表示该任务的Future
             exec.submit(read);
    
            /*
             * 四个写线程
             */
             for (int index = 0; index < 4; index++) {
                // 写线程
                final int num = index;
                Runnable write = new Runnable() {
                    String threadName = "Write" + num;
    
                    public void run() {
                        while (true) {
                            try {
                                Thread.sleep(randomTime());
                                // 调用AtomicInteger的incrementAndGet(),以原子方式将当前值加1并返回新值
                                int index = wc.incrementAndGet();
                                // 获取并移除此队列的头部,必要时在元素变得可用之前一直保持等待
                                File file = queue.take();
                                /*
                                 * 队列中已无对象
                                 */
                                 if (file = exitFile) {
                                    // 再次添加exitFile标志,以便让其余线程正常退出
                                    queue.put(exitFile);
                                    break;
                                 }
                                 System.out.println(threadName + ":" + index + " " + file.getPath());
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                };
                exec.submit(write);
             }
            exec.shutdown();
        }
    }
    

    总结

    • AtomicInteger是在使用非阻塞算法时实现并发控制,在一些高并发的场景中非常适用

    相关文章

      网友评论

          本文标题:并发编程之原子变量AtomicInteger详细解析

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