欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

悲观锁和乐观锁的区别

程序员文章站 2022-06-02 11:05:48
...

       由于数据库是多用户共用,并发情况下数据存在“脏读”、“幻读”、“不可重复读”等情况,由此引入了锁的概念,用来保持数据的一致性。

       针对不同的场景,数据库有悲观锁和乐观锁两种两种机制。

       1、悲观锁

        1)定义:悲观锁默认在当前线程处理这条数据的时候,会有其他线程对这条数据进行修改,所以在当前线程获取这条记录的时候就会进行加锁,其他线程只能等待,直到当前线程的事务结束,其他线程才能拿到锁,进行处理。

         2)应用场景:悲观锁对数据的处理都会加锁,导致其他线程无法获取数据,效率较低,但是数据较为安全,适合修改较为频繁的场景。

         3)实现方式:通过数据库的锁机制来实现,只有通过数据库的锁机制,才能保证数据的的排他性,如果在系统中,不能保证其他系统对数据的影响。锁机制有:行级锁、表级锁、页级锁、共享锁、排他锁等,其*享锁有称为“读锁”,排他锁又称为“写锁”。

         4)问题:

             ①悲观锁导致其他线程阻塞,线程被挂起;

             ②可能出现优先级高的线程等待优先级低的线程,出现风险;

             ③加锁释放锁,影响性能;

       2、乐观锁

         1)定义:乐观锁默认其他线程不会修改当前线程获取的数据,获取数据时不会进行加锁,只有在提交数据时,才会校验数据是否更新被修改,如果数据违背修改则直接提交,如果数据已修改,则需要重新更新数据,重新提交,直到成功。

         2)应用场景:乐观锁只有在提交数据的时候才会检查数据是否修改,数据吞吐较快,适合数据修改少,查询读取较多的场景。

         3)实现方式:

             ①版本号:每条数据都加上一个版本号,获取数据时获取到当前的版本号,数据处理完成,提交的时候,检查数据的版本号与之前获取的版本号是否一致。如果一致则提交记录,同时版本号加一,示意语句:

update table set data = data, version = version + 1 where version = 获取的version;

                 如果发现版本号不一致,说明记录已经被其他人修改过,则需要获取更新后的记录,然后重新提交修改,直到成功。

              ②CAS:Compare and Swap(比较和交换),主要包含三个参数,内存位置(V)、预期值(A)、修改值(B),当乐观锁提交数据时,会去内存V的位置获取记录,与预期值A作比较,如果一致,则把修改值B更新到A所在的位置;如果从内存V获取的值与A不一致,则使用获取到的新数据重新处理提交。

          4)问题:乐观锁提交的时候检查更新,如果有修改则需要重新更新处理,重新提交,一直回旋处理,直到成功。但是如果回旋时间过长,会导致CPU开销较大,影响性能。

       3、分析

             悲观锁与乐观锁说不上谁好谁坏,只是适用场景不同,在实际的开发中,要依据具体业务,合理选择使用的锁,提供安全高效的数据支持。