Package: locklib
It contains several useful additions to the standard thread synchronization tools, such as lock protocols and locks with advanced functionality.Table of contentsInstallationLock protocolsSmartLock - deadlock is impossible with itInstallationGet thelocklibfrom thepypi:pipinstalllocklib... or directly from git:pipinstallgit+https://github.com/pomponchik/locklib.gitYou can also quickly try out this and other packages without having to install usinginstld.Lock protocolsProtocols are needed so that you can write typed code without being bound to specific classes. Protocols from this library allow you to "equalize" locks from the standard library and third-party locks, including those provided by this library.We consider the basic characteristic of the lock protocol to be the presence of two methods for an object:defacquire()->None:passdefrelease()->None:passAll the locks from the standard library correspond to this, as well as the locks presented in this one.To check for compliance with this minimum standard,locklibcontains theLockProtocol. You can check for yourself that all the locks match it:frommultiprocessingimportLockasMLockfromthreadingimportLockasTLock,RLockasTRLockfromasyncioimportLockasALockfromlocklibimportSmartLock,LockProtocolprint(isinstance(MLock(),LockProtocol))# Trueprint(isinstance(TLock(),LockProtocol))# Trueprint(isinstance(TRLock(),LockProtocol))# Trueprint(isinstance(ALock(),LockProtocol))# Trueprint(isinstance(SmartLock(),LockProtocol))# TrueHowever! Most idiomatic python code using locks uses them as context managers. If your code is like that too, you can use one of the two inheritors of the regularLockProtocol:ContextLockProtocolorAsyncContextLockProtocol. Thus, the protocol inheritance hierarchy looks like this:LockProtocol
 ├── ContextLockProtocol
 └── AsyncContextLockProtocolContextLockProtocoldescribes the objects described byLockProtocol, which are alsocontext managers.AsyncContextLockProtocol, by analogy, describes objects that are instances ofLockProtocol, as well asasynchronous context managers.Almost all the locks from the standard library are instances ofContextLockProtocol, as well asSmartLock.frommultiprocessingimportLockasMLockfromthreadingimportLockasTLock,RLockasTRLockfromlocklibimportSmartLock,ContextLockProtocolprint(isinstance(MLock(),ContextLockProtocol))# Trueprint(isinstance(TLock(),ContextLockProtocol))# Trueprint(isinstance(TRLock(),ContextLockProtocol))# Trueprint(isinstance(SmartLock(),ContextLockProtocol))# TrueHowever, theLockfrom asynciobelongs to a separate category andAsyncContextLockProtocolis needed to describe it:fromasyncioimportLockfromlocklibimportAsyncContextLockProtocolprint(isinstance(Lock(),AsyncContextLockProtocol))# TrueIf you use type hints and static verification tools likemypy, we highly recommend using the narrowest of the presented categories for lock protocols, which describe the requirements for your locales.SmartLock- deadlock is impossible with itlocklibcontains a lock that cannot get into thedeadlock-SmartLock, based onWait-for Graph. You can use it as a usualLockfrom the standard library. Let's check that it can protect us from therace conditionin the same way:fromthreadingimportThreadfromlocklibimportSmartLocklock=SmartLock()counter=0deffunction():globalcounterfor_inrange(1000):withlock:counter+=1thread_1=Thread(target=function)thread_2=Thread(target=function)thread_1.start()thread_2.start()assertcounter==2000Yeah, in this case the lock helps us not to get a race condition, as the standardLockdoes. But! Let's trigger a deadlock and look what happens:fromthreadingimportThreadfromlocklibimportSmartLocklock_1=SmartLock()lock_2=SmartLock()deffunction_1():whileTrue:withlock_1:withlock_2:passdeffunction_2():whileTrue:withlock_2:withlock_1:passthread_1=Thread(target=function_1)thread_2=Thread(target=function_2)thread_1.start()thread_2.start()And... We have an exception like this:...
locklib.errors.DeadLockError: A cycle between 1970256th and 1970257th threads has been detected.Deadlocks are impossible for this lock!If you want to catch the exception, import this from thelocklibtoo:fromlocklibimportDeadLockError