一个锁实现通常会有获取(acquire)和释放(release)这两种操作:
获取操作用于取得资源的独占使用权。在任何时候,最多只能有一个进程取得锁,我们把成功取得锁的这个进程称之为锁的持有者。在锁已经被持有的情况下,所有尝试再次获取锁的操作都会失败。
代码清单 2-2 展示了一个使用字符串键实现的锁程序,这个程序会根据给定的字符串键是否有值来判断锁是否已经被获取,而针对锁的获取操作和释放操作则是分别通过设置字符串键和删除字符串键来完成的。
代码清单 2-2 使用字符串键实现的锁程序:
NX
选项的效果确保了代表锁的字符串键只会在没有值的情况下被设置:
如果给定的字符串键没有值,那么说明锁尚未被获取,
SET
命令将执行设置操作,并将result
变量的值设置为True
;
acquire()
方法最后会通过检查 result
变量的值是否为 True
来判断自己是否成功取得了锁。
释放操作 release()
方法使用了本书之前没有介绍过的 DEL
命令,这个命令接受一个或多个数据库键作为参数,尝试删除这些键以及与之相关联的值,并返回被成功删除的键数量作为结果:
release()
方法通过检查 delete()
方法的返回值是否为 1
来判断删除操作是否执行成功:如果用户尝试对一个尚未被获取的锁执行 release()
方法,那么方法将返回 false
,表示没有锁被释放。
在使用 DEL
命令删除代表锁的字符串键之后,字符串键将重新回到没有值的状态,这时用户就可以再次调用 acquire()
方法去获取锁了。
以下代码演示了这个锁的使用方法:
虽然代码清单 2-2 中展示的锁实现了基本的获取和释放功能,但它并不完美:
因为这个锁的释放操作无法验证进程的身份,所以无论执行释放操作的进程是否就是锁的持有者,锁都会被释放。如果锁被持有者以外的其他进程释放了的话,那么系统中可能就会同时出现多个锁,导致锁的唯一性被破坏。
本书后续将继续改进这个锁实现,使得它可以解决这两个问题。