• 多线程系列教材 (九)- 原子访问


    步骤1:原子性操作概念
    步骤2:AtomicInteger
    步骤3:同步测试
    步骤4:练习-使用AtomicInteger来替换Hero类中的synchronized
    步骤5:答案-使用AtomicInteger来替换Hero类中的synchronized

    步骤 1 : 原子性操作概念

    所谓的原子性操作即不可中断的操作,比如赋值操作

    int i = 5;


    原子性操作本身是线程安全的 
    但是 i++ 这个行为,事实上是有3个原子性操作组成的。
    步骤 1. 取 i 的值
    步骤 2. i + 1
    步骤 3. 把新的值赋予i
    这三个步骤,每一步都是一个原子操作,但是合在一起,就不是原子操作。就不是线程安全的。 
    换句话说,一个线程在步骤1 取i 的值结束后,还没有来得及进行步骤2,另一个线程也可以取 i的值了。
    这也是分析同步问题产生的原因 中的原理。
    i++ ,i--, i = i+1 这些都是非原子性操作。
    只有int i = 1,这个赋值操作是原子性的。

    步骤 2 : AtomicInteger

    JDK6 以后,新增加了一个包java.util.concurrent.atomic,里面有各种原子类,比如AtomicInteger
    而AtomicInteger提供了各种自增,自减等方法,这些方法都是原子性的。 换句话说,自增方法  incrementAndGet 是线程安全的,同一个时间,只有一个线程可以调用这个方法。

    package multiplethread;

       

    import java.util.concurrent.atomic.AtomicInteger;

       

    public class TestThread {

       

        public static void main(String[] args) throws InterruptedException {

            AtomicInteger atomicI =new AtomicInteger();

            int i = atomicI.decrementAndGet();

            int j = atomicI.incrementAndGet();

            int k = atomicI.addAndGet(3);

             

        }

       

    }

    步骤 3 : 同步测试

    分别使用基本变量的非原子性的++运算符和 原子性的AtomicInteger对象的 incrementAndGet 来进行多线程测试。
    测试结果如图所示

    同步测试

    package multiplethread;

    import java.util.concurrent.atomic.AtomicInteger;

    public class TestThread {

        

        private static int value = 0;

        private static AtomicInteger atomicValue =new AtomicInteger();

        public static void main(String[] args) {

            int number = 100000;

            Thread[] ts1 = new Thread[number];

            for (int i = 0; i < number; i++) {

                Thread t =new Thread(){

                    public void run(){

                        value++;

                    }

                };

                t.start();

                ts1[i] = t;

            }

             

            //等待这些线程全部结束

            for (Thread t : ts1) {

                try {

                    t.join();

                catch (InterruptedException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                }

            }

             

            System.out.printf("%d个线程进行value++后,value的值变成:%d%n", number,value);

            Thread[] ts2 = new Thread[number];

            for (int i = 0; i < number; i++) {

                Thread t =new Thread(){

                    public void run(){

                        atomicValue.incrementAndGet();

                    }

                };

                t.start();

                ts2[i] = t;

            }

             

            //等待这些线程全部结束

            for (Thread t : ts2) {

                try {

                    t.join();

                catch (InterruptedException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                }

            }

            System.out.printf("%d个线程进行atomicValue.incrementAndGet();后,atomicValue的值变成:%d%n", number,atomicValue.intValue());

        }

            

    }


    更多内容,点击了解: https://how2j.cn/k/thread/thread-atomic-access/683.html

  • 相关阅读:
    死锁
    面试题: JVM的四大引用
    面试题:对象怎么定位
    面试题: Spring框架的好处
    VTK 图形基本操作进阶_表面重建技术(等值面提取)
    VTK 图形基本操作进阶_表面重建技术(三角剖分)
    VTK 图形基本操作进阶_多分辨率策略(模型细化的三种方法)
    VTK 图形基本操作进阶_多分辨率策略(模型抽取的三种方法)
    VTK 图形基本操作进阶_连通区域分析
    VTK 图形基本操作进阶_网格模型的特征边 与 封闭性检测
  • 原文地址:https://www.cnblogs.com/Lanht/p/12615470.html
Copyright © 2020-2023  润新知