使用 python 实现简单的共享锁和排他锁

本文详细介绍了如何使用Python实现共享锁和排他锁,包括它们的概念、InnoDB中的行锁类型以及公平锁与非公平锁的区别。通过代码示例展示了锁的获取与释放,以及进行了锁兼容性和公平性测试。
摘要由CSDN通过智能技术生成

本文通过代码实操讲解了如何使用 python 实现简单的共享锁和排他锁。

上篇文章回顾:记一次容量提升5倍的HttpDns业务Cache调优

共享锁和排它锁

1、什么是共享锁

共享锁又称为读锁。

从多线程的角度来讲,共享锁允许多个线程同时访问资源,但是对写资源只能又一个线程进行。

从事务的角度来讲,若事务 T 对数据 A 加上共享锁,则事务 T 只能读 A; 其他事务也只能对数据 A 加共享锁,而不能加排他锁,直到事务 T 释放 A 上的 S 锁。这就保证了其他事务可以读 A,但是在事务 T 释放 A 上的共享锁之前,不能对 A 做任何修改。

2、什么是排它锁

排他锁又成为写锁。

从多线程的角度来讲,在访问共享资源之前对进行加锁操作,在访问完成之后进行解锁操作。 加锁后,任何其他试图再次加锁的线程会被阻塞,直到当前进程解锁。如果解锁时有一个以上的线程阻塞,那么所有该锁上的线程都被编程就绪状态, 第一个变为就绪状态的线程又执行加锁操作,那么其他的线程又会进入等待。 在这种方式下,只有一个线程能够访问被互斥锁保护的资源。

从事务的角度来讲,若事务T对数据对象A加上排它锁,则只允许T读取和修改数据A,其他任何事务都不能再对A加任何类型的锁,直到事务T释放X锁。它可以防止其他事务获取资源上的锁,直到事务末尾释放锁。

InnoDB 中的行锁

InnoDB实现了以下两种类型的行锁:

共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。 

排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB 还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。

意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的 IS 锁。

意向排他锁(IX)事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的 IX 锁。

如果一个事务请求的锁模式与当前的锁兼容,InnoDB 就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。

意向锁是 InnoDB 自动加的,不需用户干预。对于 UPDATE、DELETE 和 INSERT 语句,InnoDB 会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB 不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。

共享锁(S):

SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE

排他锁(X):

SELECT * FROM table_name WHERE ... FOR UPDATE

用 SELECT ... IN SHARE MODE获得共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用 SELECT... FOR UPDATE 方式获得排他锁。

使用Python实现

1、代码实现

不多说,直接上代码:

# -*- coding: utf-8 -*-import threadingclass Source:

# 队列成员标识
__N = None

# 排他锁
__X = 0
# 意向排他锁
__IX = 1
# 共享锁标识
__S = 2
# 意向共享标识
__IS = 3

# 同步排他锁
__lockX = threading.Lock()
# 事件通知
__events = [
threading.Event(),
threading.Event(),
threading.Event(),
threading.Event()
]
# 事件通知队列
__eventsQueue = [
[],
[],
[],
[]
]
# 事件变更锁
__eventsLock = [
threading.Lock(),
threading.Lock(),
threading.Lock(),
threading.Lock()
]
# 相互互斥的锁
__mutexFlag = {}

# 锁类
class __ChildLock:

# 锁标识
__flag = 0
# 锁定的资源
__source = None

def __init__(self, source, flag):
self.__flag = flag
self.__source = source

#
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值