Java基础之《锁》

一、什么是悲观锁?什么是乐观锁?
1、悲观锁
站在mysql的角度分析:悲观锁就是比较悲观,当多个线程对同一行数据实现修改的时候,最后只有一个线程才能修改成功(for update),只要谁能够对获取到行锁则其他线程是不能够对该数据做任何修改操作,且是阻塞状态
站在java锁层面:如果没有获取到锁,则会阻塞等待,后期唤醒锁的成本就会非常高,从新被我们cpu从就绪状态调度为运行状态
比如:lock锁(Lock是一个接口)、synchronized锁(synchronized是一个关键字)。悲观锁没有获取到锁的线程会阻塞等待
2、乐观锁
乐观锁比较乐观,通过预值或者版本号比较,如果不一致性的情况则通过死循环去重试、控制修改,当前线程不会被阻塞。是乐观、效率比较高,但是乐观锁比较耗cpu的资源
乐观锁:获取锁---如果没有获取到锁,当前线程是不会阻塞等待,通过死循环控制

二、mysql乐观锁实现原理
1、mysql层面实现乐观锁
mysql的innodb引擎自带行锁机制,多个线程无法对同一行数据同时修改的
在我们表结构中,会新增一个字段就是版本字段:version varchar(255) DEFAULT NULL
多个线程对同一行数据实现修改操作,提前查询当前最新的version版本号码,作为update条件查询,如果当前version版本号码发生了变化,则查询不到该数据
如果修改数据失败,则不断重试,又查询最新的版本号实现update
1)select version from user where user_id = ? and deleted = 0;
2)两个线程同时查询到版本号version=1
3)两个线程同时对数据进行修改
update user set user_name = ?, version = ? where user_id = ? and version = ? and deleted = 0;
两个线程都是将version=1修改成version=2
4)一个线程修改后,另一个线程update时version=1就没有数据了
那么它会重新查version是多少
2、java层面实现乐观锁
使用cas机制,如果修改失败了,通过死循环的控制不断重试
一直重试会导致cpu飙高,需要注意控制乐观锁循环的次数

三、java有哪些锁的分类
1、悲观与乐观锁
悲观锁没有获取锁会阻塞
乐观锁没有获取锁不会阻塞,通过自旋的形式做控制
2、公平锁与非公平锁
通过获取锁的排列顺序
3、自旋锁
4、重入锁
5、重量级锁与轻量级锁
6、独占锁与共享锁

四、公平锁与非公平锁
1、公平锁
就是比较公平,根据请求锁的顺序排列,先来请求的就先获取锁,后来获取锁就最后获取到,采用队列存放,类似吃饭排队
2、非公平锁
不是根据请求的顺序排列,通过争抢的方式获取锁
3、非公平锁效率比公平锁效率要高,synchronized是非公平锁
Lock锁既有公平锁也有非公平锁
new ReentrantLock(true) ---公平锁
new ReentrantLock(false) ---非公平锁
底层基于aqs实现
4、公平锁的底层是如何实现的
通过链表的形式存放
队列---底层实现方式---数组或者链表实现

五、什么是锁的可重入性
在同一线程中,锁可以不断传递的,可以直接获取
synchronized锁和lock锁都具有锁的可重用性
锁的可重入是指,当一个线程获得一个对象锁后,再次请求该对象锁时是可以获得该对象的锁的
jvm会记录下来这把锁是那个线程获取的

六、什么是CAS(自旋锁),它的优缺点
1、CAS:Compare and Swap,翻译成比较并交换,执行函数CAS(V,E,N)
CAS有3个操作数,内存值V,旧的预期值E,要修改的新值N。当且仅当预期值E和内存值V相同时,将内存值V修改为N,否则什么都不做
2、CAS没有获取到锁的线程是不会阻塞的,通过循环控制一直不断的获取锁
3、实际项目中,做计数器不用synchronized锁,用原子类
AtomicInteger
4、CAS底层实现原理
1)内存值共享变量V(0)
2)线程A第一步读取内存值V=0,作为我们预期值E=0
3)线程A判断E(0)=V(0)相等的话,则修改V=N(1)
5、CAS本质原理
旧的预期值必要要等于V(共享变量中值),才会修改我们V
CAS通过CPU硬件层面保证原子性

七、使用CAS锁的优缺点
1、CAS是通过硬件指令,保证原子性
2、Java是通过unsafe jni技术
原子类:AtomicBoolean、AtomicInteger、AtomicLong等使用CAS实现
3、优点:没有获取到锁的线程,会一直在运行态,不会阻塞,没有锁的线程一直通过循环控制重试
4、缺点:通过死循环控制,消耗CPU资源比较高,需要控制循环次数,避免CPU飙高问题

八、CAS如何解决ABA问题
1、CAS主要检查内存值V与旧的预期值E是否一致,如果一致的情况下,则修改
2、这时候会存在ABA的问题:
如果将原来的值A改为了B,B又改为了A。发现没有发生变化,实际上已经发生了变化,所以存在ABA问题
3、解决办法:通过版本号,对每个变量更新的版本号码做+1
4、ABA问题是否影响大:概念产生冲突,但是不影响结果
 

你可能感兴趣的:(JAVA基础)