高并发解决方面

架构层面:服务器上使用ngnix负载均衡,Java使用spring cloud微服务拆分。
代码层面:代码优化,算法优化,少new一些对象什么的 加锁机制
数据库层面:查询优化,读写分离,分库分表等
image.png

  • 乐观锁/悲观锁
  • 独享锁/共享锁
  • 互斥锁/读写锁
  • 可重入锁
  • 公平锁/非公平锁
  • 分段锁
  • 偏向锁/轻量级锁/重量级锁
  • 自旋锁

1、自旋锁- 自旋for来争锁 jvm默认10次
2、自旋锁的其他种类
3、阻塞锁-被阻塞的线程不会争夺锁
4、可重入锁-多次进入改锁的域 -也叫递归锁,是指在外层函数获得锁之后,内层递归函数仍然可以获取到该锁。即线程可以进入任何一个它已经拥有锁的代码块。在JAVA环境下 ReentrantLock 和synchronized 都是可重入锁。可重入锁最大的作用是避免死锁
5、读写锁
6、互斥锁-🔒本身就是互斥的 synchronized
7、悲观锁-不相信都是安全的,加把锁吧还是 不放心 synchronized
8、乐观锁-相信都是安全的
9、公平锁-有优先级 Reentrantlock(true)
10、非公平锁-没有优先级 synchronized Reentrantlock(false)
11、偏向锁-无竞争不锁,有竞争挂起转为轻量锁-指的是锁的状态 锁优化技术
12、对象锁-锁住对象
13、线程锁
14、锁粗化-多个锁变成一个 自己处理
15、轻量级锁-Cas实现 锁优化技术 锁状态
16、锁消除-偏向锁就是锁消除一种
17、锁膨胀-jvm实现锁粗话
18、信号量-使用阻塞锁 实现的一种策略
19 共享锁 ReentrantReadWriteLock 中读锁
20 分段锁 concurrentHashMap
21 独占锁 synchronized vector hashtable ReentrantReadWriteLock 中写锁
22 同步锁 synchronized
**
image.png

CAS :自旋锁 乐观锁 轻量级锁

compareAndSet CompareAndSwap
涉及问题: 1. 原子性问题 lock cmpexchgq 内存所在的缓存加了一把锁-缓存行锁(加锁只能加一个缓存行,如果值比较大就在总线上加锁)
先比较再替换 (底层c++实现,调用汇编指令,不同cpu有不同的实现)(1.)比较 (2)set 再一二部中间如果有其他线程修改了这个值,会涉及多线程并发操作的安全问题
2.ABA问题
ABA问题的根本在于cas在修改变量的时候,无法记录变量的状态,比如修改的次数,否修改过这个变量。这样就很容易在一个线程将A修改成B时,另一个线程又会把B修改成A,造成casd多次执行的问题。
加一个版本号就可以解决
AtomicStampedReference解决 带版本号
image.png

Synchronized 重量级锁 可重入锁

锁优化 锁升级 锁消除
image.png
轻量级锁一定比重量级锁性能高吗 不一定 大量先成加锁 大量cpu自旋 空转 耗费cpu 还不如放到等待队列 不耗费cpu 虽然涉及到上下文切换 但是远远不及

对象组成:类实例
image.png

  • 对象头:

mark word :锁状态标记 锁线程id 是否加过锁
meta data :指向初始化对象所在的类-加载到元空间 对象放到堆 类放到元空间 指向原空间的类

  • 实例数据 data 记录成员变量

image.png

image.png

001 无状态偏向锁
101 有状态
jvm默认4s后开启偏向锁 可以通过 -XX:BiasedLockingStartupDelay=0 取消掩饰 如果不要偏向锁, 通过
-XX:UseBiasedLocking=false 来设置
image.png
释放了也不会释放偏向锁 , ->轻量级锁- >重量级锁,指向对象内部monitor(地址)
为什么两三个线程竞争就会升级锁 因为cas自旋争取锁,导致升级,自适应自旋

cas

底层的硬件级别保证一定是原子的,同一时间只有一个线程可以执行cas先比较在设置,其他线程此时去执行会失败
image.pngimage.png