项目场景:开发过程中经常会遇到并发的应用场景。例如:服务应用启动后,需要简单统计接口的总访问量;实时更新订单状态和交易总额。问题描述:比如统计接口访问次数,如下实现,在并发访问下,统计不准确。私人intviewCount=0;privatevoidaddViewCount(){viewCount++;}比如两个线程A和B同时访问,各自从JVM主存中加载变量viewCount到线程内存中。viewCount的值为0,每次+1,update对于JVM主存也是1。A和B实际执行完成后,JVM的值应该是2。解决方案:解决并发问题其实有两种方式:带锁和不带锁。锁是关键字synchronized,重入锁ReentrantLock。无锁有四种类型:局部变量、不可变对象、CAS原子类和ThreadLocal。具体解决方案分析:1、无锁模式1、局部变量/***局部变量,多线程更新计数时,每次在线程内存中创建i个变量。*/publicvoidlocalParam(){intcount=0;/*业务处理,统计*/count++;System.out.println(计数);}2。不可变对象车辆位置实时更新,传统的setY,setY,并发过程中会出错。定义一个finallocaltion类,构造函数直接初始化x,y。/***车辆位置经纬度值*/publicfinalclassLocation{privatefinaldoublex;私人决赛双y;公共位置(双x,双y){this.x=x;这个.y=y;}}同时定义一个traker类,用来存储多辆车的位置信息。更新时,直接使用新的location位置类更新ConcurrentHashMap。/***不可变类实现并发更新安全*通过每次更新位置,直接初始化一个新的位置,然后设置到车辆位置图上*/publicclassCarLocationTracker{/***车辆代码对应车辆位置信息映射*ConcurrentHashMap使用CAS+synchronized保证并发安全*/privateMaplocationMap=newConcurrentHashMap<>();/***更新车辆位置**@paramcarCode车辆代码*@paramnewLocation车辆新位置*/publicvoidupdateLocation(StringcarCode,LocationnewLocation){locationMap.put(carCode,newLocation);}/***获取车辆位置**@paramcarCodeVehiclebin?*@return*/publicLocationgetLocation(StringcarCode){returnlocationMap.get(carCode);}}3.ThreadLocalThreadLocal变量,线程局部变量。同一个ThreadLocal中包含的对象在不同的??线程中有不同的副本。privatestaticfinalThreadLocalthreadCount=newThreadLocal();/***ThreadLocal变量,线程局部变量*/publicvoidthreadLocalParam(){Integercount=(Integer)threadCount.get();/*业务处理,统计*/count++;System.out.println(计数);}4。CAS原子CAS机制,三种基本操作:内存地址V,旧期望值A,要修改的新值B,只有当内存地址V对应的值等于旧期望值A时,内存地址对应的值V将被更新为B.privateAtomicIntegercounter=newAtomicInteger(0);/***cas原子类是一个高并发性能的乐观锁。通过compareandswap比较替换的原子设计,read从jvm主存中读取旧值oldV。*更新时,先比较oldV与主存中的v是否相等,若相等则将v替换为newV;如果不等于,则继续while循环,从主内存中读取“新”旧值oldV。**底层用c++实现,保证三个步骤在硬件层面执行,是原子的,或者三个步骤一起执行成功,直到成功才继续循环。*/publicvoidatomicAdd(){//比如统计接口访问总数System.out.println(counter.incrementAndGet());}2.锁定模式1.关键字synchronized//访问统计privateintviewCount=0;publicsynchronizedvoidsyncAdd(){addViewCount();}privatevoidaddViewCount(){viewCount++;}2。ReentrantLock//悲观锁privateReentrantLocklock=newReentrantLock();//访问统计privateintviewCount=0;privatevoidaddViewCount(){viewCount++;}/***在执行方法之前,加一把锁;执行后主动释放锁,保证int++并发安全*/publicvoidlockAdd(){lock.lock();尝试{addViewCount();}最后{锁。开锁();}}