赞
赏
锁的作用就是某个 线程 在访问某个资源时先锁住,防止其它线程的访问,等访问完毕解锁后其他线程再来加锁进行访问。
Python 的 threading 模块提供了 Lock 和 RLock 两个类,即互斥锁和递归锁。
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。
死锁是锁的一种错误使用状态,编程过程中,不应出现死锁的情况。
每个资源都对应于一个可称为 “互斥锁” 的标记,这个标记用来保证在任意时刻,只能有一个线程访问该资源,其它的线程只能等待。
互斥锁是传统并发编程对共享资源进行访问控制的主要手段,在 Python 中,threading 模块提供了相关互斥锁的操作,互斥锁的操作主要涉及到两个操作,即 acquire 和 release。acquire 锁定当前的共享资源,release 进行解锁。
在使用互斥锁时,一定要注意:对资源操作完成后,一定要解锁,否则会出现流程执行异常,死锁等问题。
from threading import Thread,Lock
# 创建互斥锁
lock = threading.Lock()
# 对需要访问的资源加锁
lock.acquire()
# 资源访问结束解锁
lock.release()
互斥锁的使用,需要使用 threading.Lock() 创建一个互斥锁对象,接着对需要加锁访问的资源使用 lock.acquire()
进行加锁即可,最后,资源访问结束,使用 lock.release()
进行解锁即可。
使用 lock.acquire() 和 lock.release() 操作临界资源
import threading
num = 0
# 创建互斥锁
lock = threading.Lock()
def handler_incry():
global num
for i in range(100000):
num += 1
print("handler_incry done, num =", num)
def handler_decry():
global num
for i in range(100000):
num -= 1
print("handler_decry done, num =", num)
if __name__ == '__main__':
print("嗨客网(www.haicoder.net)")
# 创建线程
t1 = threading.Thread(target=handler_incry)
t2 = threading.Thread(target=handler_decry)
# 启动线程
t1.start()
t2.start()
t1.join()
t2.join()
程序运行后,控制台输出如下:
首先,我们定义了一个 int 类型的全局变量 num
,同时,我们使用 threading.Lock() 创建了一个互斥锁对象 lock。
接着,我们创建了一个 handler_incry
函数 和一个 handler_decry
函数,handler_incry
函数使用 for 循环 将全局变量 num
的值加 100000 次,执行完毕后,打印当前的 num 的值。
handler_decry
函数将全局变量 num
的减 100000 次,执行完毕后,打印当前的 num 的值,同时,我们创建了两个线程 t1 和 t2,他们的线程处理函数是我们上面定义的 handler_decry
和 handler_incry
。
最后,在 main 函数,我们开启了两个线程,并且使用 join 等待线程的结束。程序运行后,我们发现,程序的输出乱了,线程 t1 输出了一半,线程 t2 再次来输出了,这就是线程并发导致的问题。因此,我们修改程序为如下:
import threading
num = 0
# 创建互斥锁
lock = threading.Lock()
def handler_incry():
global num
lock.acquire()
for i in range(100000):
num += 1
print("handler_incry done, num =", num)
lock.release()
def handler_decry():
global num
lock.acquire()
for i in range(100000):
num -= 1
print("handler_decry done, num =", num)
lock.release()
if __name__ == '__main__':
print("嗨客网(www.haicoder.net)")
# 创建线程
t1 = threading.Thread(target=handler_incry)
t2 = threading.Thread(target=handler_decry)
# 启动线程
t1.start()
t2.start()
t1.join()
t2.join()
程序运行,如下:
我们修改程序,我们在对全局变量 num 进行增加之前使用了 lock.acquire() 进行了加锁,同时,在对变量 num 访问结束时,再次进行解锁,并且,在两个线程处理函数都使用了这个锁。
因此,现在,不管我们运行多少次我们的程序,最终的输出都不会再混乱,因为锁的存在,保证了永远只可能有一个线程在访问和操作全局变量,这样通过锁的机制,就保证了多线程访问共享资源的线程安全问题。
Python 的 threading 模块引入了互斥锁(Lock)。threading 模块提供了 Lock 和 RLock 两个类,即互斥锁和递归锁。python 互斥锁语法:
from threading import Thread,Lock
# 创建互斥锁
lock = threading.Lock()
# 对需要访问的资源加锁
lock.acquire()
# 资源访问结束解锁
lock.release()
文章目录