2021-09-15
Java培训 好程序员 北京Java培训
分布式是一种解决高并发的技术方案,那么在分布式环境下如果出现高并发时怎么处理大量数据呢?作为一个Java程序员怎么能不会这种技术呢? 、
参加过好程序员Java培训的同学应该都知道,想要解决这个问题,我们首先要搞定4把锁,它们分别就是: 乐观锁CAS、悲观锁synchronized,Lock、Redis实现分布式锁、Redisson实现分布式锁。
大多数情况下,单体应用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锁是都传统的基于JVM实现的锁。
保证某一段代码同一时间内只能有一个线程在执行,如果其他线程需要执行这段代码,在外部等待或者是尝试获取当前锁资源。
synchronized的使用成本相对Lock锁要低一些。
Lock锁需要手动释放资源,并且提供了大量的API操作。
synchronized实现原理
:synchronized是基于对象实现的锁,对象会保存到堆内存中,有一块保存对象信息的区域叫对象头,在对象头中又包含了另一个内容,MarkWord存储了当前对象的大量锁信息还有GC信息。最底层是指向了C++中ObjectMonitor,在ObjectMonitor中包含了count,owner,EntryList
Lock锁实现原理
:基于AQS实现的,在AQS中维护了一个volatile修饰的state变量,多线程在竞争锁资源时,基于CAS尝试将state变量从0修改为1,哪个线程成功的修改了,代表当前线程获取到了锁资源。没有获取到锁资源的线程会被维护到AQS中维护的Node队列里。
在分布式环境下,传统的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又进来了
Redisson是Redis的一个客户端,是一个功能相对更完善的一个客户端……
Redisson在设置分布式锁的时间,采用了lua脚本实现的,通过hash结构设置的分布式锁……
Redisson在生存时间方面提供了一个看门狗的概念,看门狗就是在设置锁资源成功后,开启的一个独立的线程,这个线程会在一定时间内,重置Redis中key的生存时间。如果当前获取锁资源的线程执行结果,任务会自动取消。
以上就是关于高并发下数据处理方案的关键4把锁,如果看文档还是不太了解的同学,可以到好程序员官网查看相关的Java培训视频教程。
开班时间:2021-04-12(深圳)
开班盛况开班时间:2021-05-17(北京)
开班盛况开班时间:2021-03-22(杭州)
开班盛况开班时间:2021-04-26(北京)
开班盛况开班时间:2021-05-10(北京)
开班盛况开班时间:2021-02-22(北京)
开班盛况开班时间:2021-07-12(北京)
预约报名开班时间:2020-09-21(上海)
开班盛况开班时间:2021-07-12(北京)
预约报名开班时间:2019-07-22(北京)
开班盛况Copyright 2011-2023 北京千锋互联科技有限公司 .All Right 京ICP备12003911号-5 京公网安备 11010802035720号