俗话说金三银四,不论是为了升职加薪仍是打算换个环境,如今正是广大程序员们的跳槽季,IT行业正暗流涌动腥风血雨,互联网寒冬彷佛并无过去,不少企业依然在裁人,还有部分企业光明正大的实行着"996",这一行可能正面临着最大的竞争压力和生存压力。咱们没法改变环境,也没法左右市场,可是咱们能改变和左右的是本身的知识深度和广度,只有武装到牙齿,不断的充实本身,才能在面试这场江湖纷争里游刃有余。mysql
你是否是常常被面试官突如其来的问题问的语无伦次或者毫无底气?进而在一整场面试里都失去了信心。最近有个群员就遇到这个问你,面试官让他自我介绍之后,就忽然问他mysql的悲观锁和乐观锁区别,而这正好是他的盲区,第一个问题就被堵住了,这场面试的结果也可想而知。下面就从面试角度来浅谈一下,该怎样回答这个问题。程序员
1、概念上区别面试
乐观锁(** Optimistic Locking**):顾名思义,对加锁持有一种乐观的态度,即先进行业务操做,不到最后一步不进行加锁,"乐观"的认为加锁必定会成功的,在最后一步更新数据的时候再进行加锁。sql
悲观锁**(Pessimistic Lock)**:正如其名字同样,悲观锁对数据加锁持有一种悲观的态度。所以,在整个数据处理过程当中,将数据处于锁定状态。悲观锁的实现,每每依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,不然,即便在本系统中实现了加锁机制,也没法保证外部系统不会修改数据)。数据库
2、实现方式:线程
乐观锁:code
version方式:通常是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,不然重试更新操做,直到更新成功。内存
sql实现代码:资源
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
CAS(定义见后)操做方式:即compare and swap 或者 compare and set,涉及到三个操做数,数据所在的内存值,预期值,新值。当须要更新时,判断当前内存值与以前取到的值是否相等,若相等,则用新值更新,若失败则重试,通常状况下是一个自旋操做,即不断的重试。(这种方式做者也是最近刚知道,惭愧惭愧)io
悲观锁:是由数据库本身实现了的,要用的时候,咱们直接调用数据库的相关语句就能够了(原理:共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程),如行锁、读锁和写锁等,都是在操做以前加锁,在Java中,synchronized的思想也是悲观锁。
3、使用场景
乐观锁:比较适合读取操做比较频繁的场景,若是出现大量的写入操做,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层须要不断的从新获取数据,这样会增长大量的查询操做,下降了系统的吞吐量。
悲观锁:比较适合写入操做比较频繁的场景,若是出现大量的读取操做,每次读取的时候都会进行加锁,这样会增长大量的锁的开销,下降了系统的吞吐量。
4、特色
乐观锁:乐观锁的特色先进行业务操做,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,所以在进行完业务操做须要实际更新数据的最后一步再去拿一下锁就好。
悲观锁:悲观锁的特色是先获取锁,再进行业务操做,即“悲观”的认为获取锁是很是有可能失败的,所以要先确保获取锁成功再进行业务操做。一般所说的“一锁二查三更新”即指的是使用悲观锁。
5、sql实现代码和案例
由于本文主要是讲解的是面试的时候怎样回答,因此就不将具体sql代码和案例贴出来了,感兴趣的同窗能够自行去看一下,若是之后有时间,我也会单独写一篇详细的实现案例出来。
总结:以上,基本回答完前四点后,这道题已经能在面试官内心达到八九十分了。可是咱们的人生不只仅是为了面试,但愿同窗们必定要弄懂其中的原理和区别,悲观锁和乐观锁都有本身的优缺点,简而言之记得一句话:读取频繁使用乐观锁,写入频繁使用悲观锁。乐观锁不能解决脏读的问题。
若是以为本文有用,请推荐给更多有须要的人,谢谢!若是发现问题,欢迎留言,请随时批评改正,谢谢!