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

python锁机制

程序员文章站 2022-06-22 11:25:02
python多进程,多线程之锁机制 锁添加的原因: 在多进程/多线程同时进入临界资源区获取和操作共有资源时,会出现资源的争夺而出现混乱。为了避免这种混乱现象,python提出了锁机制 线程锁/进程锁的定义和运用: 创建锁对象: lock = Lock() 锁对象一旦创建,就可以随时被进程或者线程调用 ......

python多进程,多线程之锁机制

锁添加的原因:

在多进程/多线程同时进入临界资源区获取和操作共有资源时,会出现资源的争夺而出现混乱。为了避免这种混乱现象,python提出了锁机制

 

线程锁/进程锁的定义和运用:

创建锁对象:

lock = lock()

锁对象一旦创建,就可以随时被进程或者线程调用,并且一次创建锁只有一把,如果多个资源想同时获取锁,必须‘排队’,等上一个进程/线程释放了锁才可以请求获取锁

 

上锁(也叫请求锁)

lock.acquire()

acquire()是一个阻塞函数。一旦请求获取锁成功,就会把下面将要执行的程序的变量内存空间‘锁住’;而获取不成功则会一直阻塞在那里,等待上一个获得锁的进程/线程释放锁。

 

解锁

lock.release()

 

 

死锁:

死锁的出现有两种情况

1) 当一个进程或者一个线程一直调用或者占用同一锁lock而不释放资源而导致其他进程/线程无法获得锁,就会出现的死锁状况,一直阻塞在aquire()处

2) 当有两个进程同时想获取两个锁的时候(再往上推就是多个进程想获取多个锁),由于两者都是出于竞争关系,谁也不让谁,谁快谁得手,但计算机中这种竞争关系是很微妙的,时间的差异性很小,于是,就出现了两者都阻塞在同一个地方,都无法同时获得两个锁或者获取对方已经获取的但还没有释放的锁。

 

为了解决死锁的问题,于是python提出了可重入锁的机制(rlock)

重入锁定义后,一个进程就可以重复调用指定次数的一个重入锁,而不用去跟别的进程一起争夺其他锁。

 

重入锁中内部管理者两个对象,即lock对象和锁的调用次数count

下面说说rlock到底是怎么用的

1)rlock的定义

mutexa = mutexb = rlock( )

mutex值可以是多个的,定义了多少个,rlock内部的count就为几

 

2)rlock的请求

mutexa.acquire()

mutexa.acquire()

 

每申请一次锁,count就减1,两次请求过后,count从2减为0

 

因为上面定义的重入锁的内部个数为2,所以该重入锁可以被一个进程调用两次,并且在虽然它内部有多个锁,但只能由一个进程/线程调用,其他进程/线程不能干预,只有当这个进程/线程释放掉所有的重入锁,count=2时才可以被其他进程/线程调用。

 

3)rlock锁的释放

mutexa.release()

mutexb.release()

 

举例:

from multiprocessing import rlock,process
from time import ctime,sleep

muxtea = mutexb =rlock()

def fn1():
    muxtea.acquire()
    sleep(1)
    print(ctime(),'进程1获取a锁')
    mutexb.acquire()
    sleep(2)
    print(ctime(),'进程1获取b锁')
    muxtea.release()
    print('进程1释放a锁')
    mutexb.release()
    print('进程1释放b锁')

def fn2():
    muxtea.acquire()
    sleep(1)
    print(ctime(),'进程2获取a锁')
    mutexb.acquire()
    sleep(1)
    print(ctime(),'进程2获取b锁')
    muxtea.release()
    print('进程2释放a锁')
    mutexb.release()
    print('进程2释放b锁')


p1 = process(target=fn1)
p2 = process(target=fn2)
p1.start()
p2.start()

p1.join()
p2.join()

 结果如下:

python锁机制

 

那么如果我让进程2先开启呢?

python锁机制

 

结果如下:

python锁机制

 

显然,锁的获得是谁快谁得手,同时也验证了我上面描述的,一个进程对一个可重入锁的请求是排他型的,一旦这个进程请求了一个可重入锁,那么其他进程就无法再请求了,直到这个进程释放了可重入锁内部的所有锁。