关于Python多线程同步问题
-
场景描述
场景描述:我们设有两个并发的线程( 线程A 和 线程B ),需要 资源1 和 资源2 .假设 线程A 需要 资源1 , 线程B 需要 资源2 .在这种情况下,两个线程都使用各自的锁,目前为止没有冲突。现在假设,在双方释放锁之前, 线程A 需要 资源2 的锁, 线程B 需要 资源1 的锁,没有资源线程不会继续执行。鉴于目前两个资源的锁都是被占用的,而且在对方的锁释放之前都处于等待且不释放锁的状态。这是死锁的典型情况。所以如上所说,使用锁来解决同步问题是一个可行却存在潜在问题的方案。
-
使用默认Lock进行同步
特点: 通过 threading.Lock 我们可以将共享资源某一时刻的访问限制在单一线程或单一类型的线程上,线程必须得到锁才能使用资源,并且之后必须允许其他线程使用相同的资源。 结论: 默认多线程操作共享变量是线程不安全 使用默认锁是线程安全的,但是当存在多个锁的情况下需要注意锁的加锁顺序,并且acquire release必须成对存在
- Rlock
特点: 递归锁可被同一线程多次acquire 谁拿到谁释放 多次acquire后必须多次release 结论: 可以实现对共享变量的控制达到线程安全
-
信号量
特点: 通过设置信号量的初始值,可以明确的表示共享变量最多可被多少线程使用,其工作原理是通过对信号量的值的控制(acquire release)达到对共享变量的使用。 具体实现是通过acquire获取变量时,会减少信号量的值,如果此时变量的值为负,则该线程会被挂起,直到其他线程release资源后才能使用该变量。 如果通过acquire后变量值为正,那么线程可正常获取该资源。 定义信号量,初始值为0,达到多线程同步效果,只有信号量的值为正时线程才可以获取共享变量的所有权 semaphore = threading.Semaphore(0) 结论:信号量可以实现对共享变量的控制,但是当存在多个信号量,多线程调用的时候依旧会发生死锁。
-
Condition
特点: 当想要通过某些条件触发线程时,可以通过条件进行操作。 这是另一种同步机制,其中某些线程在等待某一条件发生,其他的线程会在该条件发生的时候进行通知。一旦条件发生,线程会拿到共享资源的唯一权限。