• java并发编程学习笔记(一)初识并发原子性


    1、并发的意义

        现在是一个多核的时代,并发的存在意义就是为了能够充分利用多核计算机的优势,提高程序的运行效率;

    2、并发的风险

        竞争-----多个线程对内存数据数据进行读写操作时,对数据处理结果的一个竞争。(笔者是这么认为的)

        使用以下的例子来说明并发的风险:由于该方法中的value++操作不是原子性的,是分为读->运算->赋值 这3个步骤的。

        假如线程A执行了读,正准备开始运算的时候,线程B开始调用这个实例的getNext方法,那么这个时候线程B读取的数据与线程A读取的数据是一样的。

         即A获得的结果是value=value+1;线程B运算也是value=value+1;然而线程B在线程A之后才调用这个方法,按照假设,线程B应该返回value+2才对。

        ps:文字描述的value就是初始值。

        

    public class  demo {
    
     private int value;
    
      public int getNext(){
        return value++;
      }
    }
    

     3、上述问题产生的原因有2个:

            1 线程共享内存的地址空间(即内存数据对2个线程都可见)

            2 getNext方法并不是原子性的(内部代码执行是可分割的)

            这样就容易产生 竞争条件。

          总结:线程共享相同的内存地址空间,可以访问或修改其他线程正在使用的变量。这对于线程间的通信,是十分方便的。但是其中存在着数据意外变更的风险,因此访问共享的内存变量时,线程需要经过合理的调度,才能保证程序的正常运行。

    4、要纠正上述问题,可以从2个方面着手,现在先从第二个原因来着手解决。(非原子化操作)

        目标1:将value++的操作原子化。

                使用原子类AutomicInterger  来代替 int类型 

                自增操作就可以写为value.incrementAndGet();

        这样一来,线程对数据的操作就是原子化的,不会出现竞争条件。

       目标2:内存数据对2个线程同时都可读写,可使用->修改为以下状态

                 状态一:只对单个线程可读写(某个线程正在使用该对象时,另一个线程无法获取并使用该对象,另一个线程进入阻塞状态)

                 状态二:两个线程都可读,但是只对一个线程开放数据修改权限

                

                以上两个状态:需要使用到锁,在下一节中做详细介绍。

                 

  • 相关阅读:
    JS随笔
    tp5 redis 单例模式 转载
    分享我编程工作经历及对软件开发前景的看法
    redis详解(一)-- 概述
    redis详解(二)-- 数据类型详解
    redis详解(四)-- 高可用分布式集群
    redis详解(三)
    新工科平台
    关于Nginx的负载均衡
    微信退款回调
  • 原文地址:https://www.cnblogs.com/LingoXu/p/5252146.html
Copyright © 2020-2023  润新知