乐观锁:预测锁冲突的概率不是很高(因此所做的工作就可以简单一些)干的事情少
悲观锁:预测锁冲突的概率教高(因此所做的工作就要复杂一些)干的事情多
(锁冲突指的是多个线程竞争同一把锁)
就好比A同志和B同志,A同志睡觉的时候不习惯锁门睡觉,于是门没有锁就直接睡,觉得B同志应该不会来自己的房间(乐观锁)而B同志就习惯了锁门睡觉怕A同志会来打扰自己(悲观锁)
读写锁和普通互斥锁:
普通的互斥锁就好比如synchronized,当两个线程共同竞争同一把锁的时候,一个线程拿到了锁,另一个线程就得等待
读写锁分为两种情况:
1.加读锁:多个线程同时读一个变量(加读锁)
2.加写锁:多个线程修改同一个变量(加写锁)
读锁和读锁之间,不会产生竞争
写锁和写锁之间,会产生竞争
读锁和写锁之间,会产生竞争
往往在实际的场景中,读的场景很多,而写的场景很少。
读写锁相比于普通的互斥锁,减少了很多的锁竞争,优化了效率
重量级锁和轻量级锁:
重量级锁:加锁和解锁的开销比较大(进入内核的加锁逻辑,开销比较大,因为内核比较忙啥时候给你做这件事不清楚,但一定能给你做了)
轻量级锁:加锁和解锁的开销比较小(纯用户的加锁逻辑,开销比较小,自己想去完成一件啥事,自己立马就去做了,自己动手丰衣主食)
乐观锁指是是干的事情比较少,悲观锁指的是干的事情多。是站在过程上来决定干的事情多不多的。而重量级锁和轻量级锁是站在结果的角度上来看待最终的加锁解锁消耗的时间是多还是少。在通常的情况下(但是不绝对哈)我们可以认为干的工作多,那么消耗的时间也就比较多,所以在一般的情况下(不是绝对)认为乐观锁一般也比较轻量,而悲观锁,一般也比较重量。但是也是不绝对的哈。
自旋锁和挂起等待锁:
自旋锁:是轻量级锁的一种典型实现
类似于“忙等”,会消耗大量的资源,CPU占用率比较高;但是能第一时间获取到锁
挂起等待锁:是重量级锁的一个典型实现
可以先挂起等待,去做另外的事情,可以把时间和资源都利用起来,但是获取到锁的时间就没那么及时了
公平锁和非公平锁:
操作系统默认的锁的调度,是非公平的情况
如果要实现公平锁,那么需要引入额外的数据结构来记录线程加锁的顺序,则需要一等的开销
可重入锁和不可重入锁:
可重入锁:同一个线程针对与同一把锁,连续加锁两次,该线程不会死锁;
不可重入锁:同一个线程针对与同一把锁,连续加锁两次,该线程会死锁;
对于synchronized:
1.既是乐观锁也是悲观锁
2.既是轻量级锁又是重量级锁
3.乐观锁的部分是基于自旋锁实现的,悲观锁的部分是基于挂起等待所锁实现的。
所以可以得出synchronized是自适应的,当初次使用的时候,是乐观锁/轻量级锁/自旋锁。如果锁竞争不是很激烈那么上述的状态不变,但是如果锁竞争比较激烈的情况下,synchronized就会自动的升级成为悲观锁/重量级锁/挂起等待锁——这是JVM在实现synchronized的时候给程序员提供的自动优化的策略,所以一个synchronized自动适应多种不同的场景就特别的智能,能够简化程序员的开发成本
4.是普通互斥锁,不是读写锁
5.是非公平锁
6.是可重入锁