本文主要回答如下问题:
- 什么是锁机制?
- 锁机制的作用是什么?
- 锁机制的类型有哪几种?
关键字:并发、并发控制、乐观锁、悲观锁
在我们常见的程序设计、操作系统和数据库等领域,并发是非常棘手的问题之一。而并发在操作系统、数据库等领域,最终还是会体现在软件开发(代码实现)上。并发的主要纠结点在于对共享资源的处理,虽然现在有事务来处理并发,但是这只是在一定程序上缓解了并发的问题,并没有彻底解决,比如跨事务的并发。
在软件开发过程中,并发控制是确保及时纠正由并发操作导致的错误的一种机制。并发控制主要采用时间戳、乐观并发控制和悲观并发控制等技术手段来实现。而今天我们要说的锁机制主要是指后面的两种技术手段:乐观并发控制和悲观并发控制,他们分别对应乐观锁和悲观锁。锁机制是管理对共享资源的并发访问机制。
乐观锁并不是纯粹意义上的锁,它可以理解为冲突检测,属于事后的操作,其中一种实现是依赖数据版本记录机制。在数据源增加一个版本标记,当请求方读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据源中对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据源当前版本号,则予以更新,否则认为是过期数据。比如某个共享数据被并发访问修改,在各个请求方获取了数据后,请求方都会被分配一个相同版本,如果有一个请求方提交了修改,则将原始数据版本增加1,则其它请求方再次提交修改时,由于提交的版本小于当前版本则显示冲突。除了基于数据版本的控制外,还有包含对更新时间的控制,对不同字段的对比控制等。
悲观锁可以理解为冲突避免,属于事前的操作,即不让并发修改的操作发生,减少并发出现。当一个用户访问一个共享对象时锁住它,即先获得锁,此时其它用户无法访问此对象,当对共享对象的操作完成以后要为被它封锁的对象解锁,此时其它对象才能访问此共享对象。如果此时一个用户一直占着一个资源不放,其它所有用户都只能永远等待,此时可能需要引入其它机制来防止这种情况的发生。
悲观锁减少了并发的程序,而乐观锁在一定程度上会更加自由一些,其在获取资源时是不受限制的,仅在提交的时候才会有限制。当需要在悲观锁与乐观锁之间抉择时,可以考虑如下两个点:
- 冲突的频率 如果冲突少,通常可以选择乐观锁,这样可以获得更多的并发性,但是此时也需要考虑冲突的严重性,如果系统不能容忍冲突的出现,则需要考虑牺牲并发性,使用悲观锁
- 冲突的严重性 如果冲突所产生的后果比较严重或者为用户不能容忍,需要使用悲观锁
无论是乐观锁还是悲观锁都存在其优点和缺点,只使用某一种机制都会产生其它问题,可以考虑将这两种锁放一起使用,或者提供两种机制,供用户选择,默认使用乐观锁。