当前位置: 首页 / 技术干货 / 正文
好程序员Java培训分享:高并发下的数据处理方案,这4把锁是关键!

2021-09-15

Java培训 好程序员 北京Java培训

分布式是一种解决高并发的技术方案,那么在分布式环境下如果出现高并发时怎么处理大量数据呢?作为一个Java程序员怎么能不会这种技术呢?    、

参加过好程序员Java培训的同学应该都知道,想要解决这个问题,我们首先要搞定4把锁,它们分别就是: 乐观锁CAS、悲观锁synchronized,Lock、Redis实现分布式锁、Redisson实现分布式锁。

一、CAS

大多数情况下,单体应用CAS可以实现轻量级锁效果

乐观锁,可以避免线程在阻塞,就绪状态之间的切换

CAS:Compare And Swap(比较和交换)

保证某个数据在被修改时,是线程安全的。

修改数据时,需要先获取到内存中的数据,在修改之前,需要将获取到的数据和内存中的数据做比较,如果一致需要将内存中的数据进行修改,如果不一致,这次修改操作作废

Java中为了实现CAS操作,调用了Unsafe类中的CAS方法,是native方法,底层是调用了本地库方法实现的

CAS在Java的JUC包的应用特别广泛

CAS也存在一些问题

ABA问题:在修改内存中数据之前,有其他线程将内存中的数据做了多次修改,最终修改为了原值,其他线程因为做比较时,值是一样的,直接修改了,这种操作是不安全的。

处理方案:采用值 + version版本号的形式……

CAS自旋次数过多:CAS经常被应用到CAS实现后,自动重试,如果并发比较大,重试次数过多,造成一些不便的CPU性能损耗。

Atomic原子类,基于CAS操作实现自增等运算操作,Atomic本事是存在这种自旋次数过多问题,提供了另一种数值原子类,LongAdder。 LongAdder可以将CAS失败的数值临时添加到Cell[]数组中存储,再后面讲Cell[]中的数据添加到当前值中。

synchronized在JDK1.6中有大量的优化,提供了自适应自旋锁,根据上一次当前锁获取消耗的时间,来决定这次CAS自旋多久,如果自旋结束,还没有获取到锁资源,将线程挂起……

二、传统锁synchronized,Lock

synchronized和Lock锁是都传统的基于JVM实现的锁。

保证某一段代码同一时间内只能有一个线程在执行,如果其他线程需要执行这段代码,在外部等待或者是尝试获取当前锁资源。

synchronized的使用成本相对Lock锁要低一些。

Lock锁需要手动释放资源,并且提供了大量的API操作。

synchronized实现原理:synchronized是基于对象实现的锁,对象会保存到堆内存中,有一块保存对象信息的区域叫对象头,在对象头中又包含了另一个内容,MarkWord存储了当前对象的大量锁信息还有GC信息。最底层是指向了C++中ObjectMonitor,在ObjectMonitor中包含了countownerEntryList

Lock锁实现原理:基于AQS实现的,在AQS中维护了一个volatile修饰的state变量,多线程在竞争锁资源时,基于CAS尝试将state变量从0修改为1,哪个线程成功的修改了,代表当前线程获取到了锁资源。没有获取到锁资源的线程会被维护到AQS中维护的Node队列里。

三、Redis实现分布式锁

在分布式环境下,传统的CAS,synchronized,Lock锁都已经失效了,如果需要保证多个服务之间依然存在互斥性,需要一个独立于容器之外的一个服务,实现锁的功能……

MySQL:MySQL也有锁的概念,让多个服务之间去竞争MySQL的行锁,只会有一个服务获取到MySQL的行锁

Zookeeper:Zookeeper基于Znode存储,提供了临时有序节点,基于写操作不存在互斥性原理,很轻易的实现锁资源,并且还解决了死锁问题。

Redis:Redis提供key-value的存储结构,Redis在读写操作都不存在并发问题,基于setnx实现获取锁资源的功能,基于setnxex在获取锁资源的基础上,还可以解决死锁问题……

Redis相对MySQL和Zookeeper效率更高,在高并发还要求效率的场景下,Redis做分布式锁是非常好的一个解决方案,但是Redis存在一些问题,Redis解决死锁问题,是通过ex设置生存时间的方式解决,生存时间不好把控。

  • 如果生存时间设置过长,导致出现死锁时,死锁时间过长……

  • 如果生存时间设置过短,导致线程A还没有执行完业务逻辑,线程B又进来了1631606396497

四、Redisson实现分布式锁

Redisson是Redis的一个客户端,是一个功能相对更完善的一个客户端……

Redisson在设置分布式锁的时间,采用了lua脚本实现的,通过hash结构设置的分布式锁……

Redisson在生存时间方面提供了一个看门狗的概念,看门狗就是在设置锁资源成功后,开启的一个独立的线程,这个线程会在一定时间内,重置Redis中key的生存时间。如果当前获取锁资源的线程执行结果,任务会自动取消。

以上就是关于高并发下数据处理方案的关键4把锁,如果看文档还是不太了解的同学,可以到好程序员官网查看相关的Java培训视频教程

好程序员公众号

  • · 剖析行业发展趋势
  • · 汇聚企业项目源码

好程序员开班动态

More+
  • HTML5大前端 <高端班>

    开班时间:2021-04-12(深圳)

    开班盛况

    开班时间:2021-05-17(北京)

    开班盛况
  • 大数据+人工智能 <高端班>

    开班时间:2021-03-22(杭州)

    开班盛况

    开班时间:2021-04-26(北京)

    开班盛况
  • JavaEE分布式开发 <高端班>

    开班时间:2021-05-10(北京)

    开班盛况

    开班时间:2021-02-22(北京)

    开班盛况
  • Python人工智能+数据分析 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2020-09-21(上海)

    开班盛况
  • 云计算开发 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2019-07-22(北京)

    开班盛况
在线咨询
试听
入学教程
立即报名

Copyright 2011-2020 北京千锋互联科技有限公司 .All Right 京ICP备12003911号-5 京公网安备 11010802035720号