「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
线程间同步
常用线程间同步方法有:
- 临界区:通过对多线程的串行化来访问公共资源或一段代码
- 速度快,适合控制数据访问
- 在任意时刻只允许一个线程访问共享资源,当有一个线程进入后,其他试图访问共享资源的线程将会被挂起,并一直等到进入临界区的线程离开,临界在被释放后,其他线程才可以抢占
- 互斥量:为协调对一个共享资源的单独访问而设计
- 只有拥有互斥量的线程,才有权限去访问系统的公共资源
- 互斥量只有一个,所以能够保证资源不会同时被多个线程访问
- 互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享
- 信号量:为控制一个具有有限数量的用户资源而设计
- 它允许多个线程在同一个时刻去访问同一个资源,但一般需要限制同一时刻访问此资源的最大线程数目
- 事件:用来通知线程有一些事件已发生,从而启动后继任务的开始
Python 中的互斥锁
互斥量又称为互斥锁,Python 的 threading
模块中定义了 Lock
类,可以方便的处理锁定。一旦某个线程获得了这个锁,其他的线程再要想获得这个锁就必须阻塞,直到锁被释放。
- 创建一个锁:
mutex = threading.Lock()
- 获得一个锁:
mutex.acquire([blocking=True, timeout=-1])
- 成功获得锁时返回
true
blocking
为ture
时,以阻塞方式获得锁,即要等到锁释放后方能加锁timeout
为超时时间,如果设定了timeout
,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理
- 成功获得锁时返回
- 释放一个锁:
mutex.release()
举个例子
import threading
num = 0
mutex = threading.Lock() # 创建一个锁
def add():
""" num 数值每次加 1,执行 1000000 次"""
global num
for _ in range(1000000):
if mutex.acquire():
num += 1
mutex.release()
t1 = threading.Thread(target= add)
t2 = threading.Thread(target= add)
# 开始线程
t1.start()
t2.start()
# 等待线程结束
t1.join()
t2.join()
print(num)
运行代码,可以看到输出 2000000
,如果去掉代码中的加锁和释放锁的语句,则会得到不符合预期的结果。