锁
锁的定义
锁是用来协调多个线程并发访问同一共享资源时带来的安全问题,频繁用锁必然会带来性能问题,但不用锁又会造成安全问题
1)从性能上分:乐观锁和悲观锁
-
乐观锁:CAS自旋锁,是非常经典的乐观锁,并发性能比较好,但是自旋会造成很大的开销,悲观的认为当前环境下并发情况不是很很严重,任务提交时才才判断是否冲突
-
悲观锁:悲观的认为当前环境下并发情况是很严重的,所有的任务在执行时都要加上锁,保证了安全型,失去了并发性,并发性能差
乐观锁:无锁,在数据提交时才去判断是否发生冲突,version
悲观锁:每次访问数据时,都需要加锁
2)从数据库操作的类型上划分
读锁和写锁,其都是悲观锁
-
读锁(共享锁):对读取同一行数据的并发来说,是可以同时进行的,但是写不行
-
写锁(排它锁):在加写锁之后释放锁之前,其他的所有操作都不能进行
3)从数据的操作粒度上来划分
表锁和行锁
-
表锁:对整张表进行上锁
- mysiam默认支持表锁,多个线程并发操作时,一个线程操作myisam后其他所有操作都不能进行
- innodb上表锁:lock table 表1 read/write/,表2 read /write
- show open tables 查看当前会话的所有锁
- unlock tables 释放当前会话的所有锁
-
行锁:对表中的某一行记录进行上锁,支持并发读其是一个读锁
-
innodb支持行锁,在并发事务里,每个事务的读写删相当于上行锁
-
上锁的开销大,加锁速度慢但是并发性更好
-
update tb_author set name=‘m’ where id=1
-
select * from tb_author where id=1 for update
-
AQS
AQS的理解
抽象队列同步器,其是并发包中的基础组件,用来实现各种锁,ReentrantLock底层由其实现包括 state变量,等待队列,加锁线程三个核心内容
实现原理:初始时state=0,加锁线程为null,线程1加锁后利用CAS判断state递增是否成功若成功加锁队列由null变为线程1,如果此时线程2也想加锁,但是state已经被使用则其进入等待队列之中,若线程1释放锁(state递减,若state=0,则彻底释放锁加锁线程为null)则从等待队列的表头唤醒线程2,重复线程1操作,如果成功则从等待队列中出列加锁线程变为线程2
事务隔离级别
事务的隔离级别
脏读:一个事务读到另外一个事务尚未提交的数据
幻读:以相同的条件,检索以前检索过的数据,发现其他事务插入了新的数据
不可重复读:一个事务在读取后的某个时间再次去读数据发现数据改变
Read uncommit 都没解决
Read commit 只解决了脏读
repeat read 没有解决幻读
serializable 都解决,最高事务级别
CAS的理解及ABA问题
CAS(compare and sort):是乐观锁的实现方式,如果多个线程CAS更新同一个变量,只有一个线程能执行,其他线程都会失败,失败的线程可以再次尝试、有内存地址V,预期原值A,新值B,V==A则V=B否则不会执行
ABA:线程E,F同时拿到了内存地址内的变量A,但是F将变量A改成B,F执行成功E执行失败
解决:在jdk1.5后提供AtomicStampedReference解决ABA
CAS缺点:ABA问题,循环时间长,开销比较大,只能保证一个共享变量的原子操作(锁去解决),浪费cpu资源
慢sql及解决
查询时没有走索引,查询时间过长导致慢sql
解决:对查询性能进行优化
方法加锁和对象加锁区别
-
方法锁:让成员变量被访问时实现同步
-
对象锁:让实例对象之间实现同步
-
类锁:让静态资源实现同步
多用户并发怎么解决?
使用了乐观锁或者悲观锁
-
乐观锁:CAS自旋锁,是非常经典的乐观锁,并发性能比较好,但是自旋会造成很大的开销,悲观的认为当前环境下并发情况不是很很严重,任务提交时才才判断是否冲突
-
悲观锁:悲观的认为当前环境下并发情况是很严重的,所有的任务在执行时都要加上锁,保证了安全型,失去了并发性,并发性能差
乐观锁:无锁,在数据提交时才去判断是否发生冲突,version
悲观锁:每次访问数据时,都需要加锁
分段锁的理解
优点:不同段的map都能并发执行
缺点:分成很多段时,容易造成内存空间不连续或者碎片化,操作map时竞争同一个锁的概率很小,容易造成更新等操作时间过长,分段锁性能降低
sql语句使用where时尽量不要使用哪些语法?
使用where时不要使用变量或者表达式(!=,>,<,1=1等)以及in和or会导致不走索引
MVCC理解及实现原理
mvcc:多版本并发控制,是一种解决读写冲突的无所并发机制,提高并发性能,让其并发操作数据库时,读操作不阻塞写操作,写操作不阻塞读操作,解决了脏读幻读不可重复的等隔离问题
实现原理:在表中默认创建了三个字段分别代表事务id,索引,和指向日志的指针,用排它锁锁定该行记录,将记录复制到undolog日志里面然后进行事务,若成功则提交,不成功则根据指针找到日志中存储的信息