python - Python线程未释放锁

标签 python python-3.x multithreading locking

在使用Python中的锁创建简单的使用者生产者线程结构时,我遇到了一些问题,这些问题导致程序创建了意外的输出。

import threading
from time import sleep
import random

class AI:
    def __init__(self):
        self.a = None
        self.mainLock = threading.Lock()
        threading.Thread(target=self.producer,daemon=True).start()
        threading.Thread(target=self.consumer,daemon=True).start()

    def producer(self):
        while True:
            self.mainLock.acquire()
            sleep(1)
            temp = random.randint(-1,10)
            print(f"Produced {temp}")
            self.a = temp
            self.mainLock.release()

    def consumer(self):
        while True:
            self.mainLock.acquire()
            if(self.a and self.a>0):
                sleep(1.5)
                print(f"Consumed {self.a}")
                self.a = None
            self.mainLock.release()

a = AI()
input()
输出 -
Produced 0
Produced 8
Produced 9
Produced 1
Produced 9
Produced 10
Produced 5
Produced 1
这显然不是这里预期的。预期的产出本来会限制生产者之后的消费者。但是,如果在释放生产者内部的锁之后添加任何语句,则代码可以正常运行。
代码 -
import threading
from time import sleep
import random

class AI:
    def __init__(self):
        self.a = None
        self.mainLock = threading.Lock()
        threading.Thread(target=self.producer,daemon=True).start()
        threading.Thread(target=self.consumer,daemon=True).start()

    def producer(self):
        while True:
            self.mainLock.acquire()
            sleep(1)
            temp = random.randint(-1,10)
            print(f"Produced {temp}")
            self.a = temp
            self.mainLock.release()
            ## = Newly added line
            ########################
            print("released")
            ########################

    def consumer(self):
        while True:
            self.mainLock.acquire()
            if(self.a and self.a>0):
                sleep(1.5)
                print(f"Consumed {self.a}")
                self.a = None
            self.mainLock.release()

a = AI()
input()
输出 -
Produced 10
released
Consumed 10
Produced 7
released
Consumed 7
Produced 2
released
Consumed 2
即使将print语句替换为sleep语句,该代码也可以工作,无论休眠持续时间有多短,仍然可以正常工作。
例子 -
sleep(0.0000000000000000000000000000000000000000000000000000000000000000000000001)
为什么会这样呢?在消费者发布之后,代码如何能够在没有任何打印或 sleep 的情况下从消费者跳回生产者,而没有这些代码,则无法从消费者跳到生产者?

最佳答案

释放锁并不能自动确保其他等待线程会立即获取该锁。
特别是,这是一种反模式:

 while (True):
     someLock.acquire()
     ...
     someLock.relase()
问题是,线程在释放锁定之后要做的下一件事是,它再次获取它。
想象一下,您在门锁着的浴室里。有人在外面等着进去。您已经让他们等了很长一段时间,所以也许他们坐下来了。突然,您打开门,走了出去,而在另一个人还没有时间站起来之前,您又走回室内并再次锁上了门。
这大致就是您的程序中正在发生的事情。
锁对一件事有好处,并且仅对一件事有好处:您可以使用它们来阻止两个线程同时使用相同的资源。如果您尝试将它们用于其他任何目的(例如,控制线程执行操作的顺序),那么您将很难。

在许多编程语言/库中,一个线程发信号通知另一个线程的最原始方法称为条件变量。参见https://docs.python.org/3/library/threading.html#condition-objects

关于python - Python线程未释放锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65905098/

相关文章:

python - python 将骰子的两个结果相加

java - 为什么我的线程不能使用 Java ExecutorService 并行运行?

java - 计算工作线程处理消息所花费的时间

python - 如何将现有的 MySQL 数据库导入到 web2py 中?

python-3.x - 使用Python 3.6.8导入geojson时返回错误

Python在postgresql表中查找带有单引号的字符串

java - 在多线程程序中缓冲数据库插入

python - 使用字典的字典来存储常量

python - 不需要的空白导致列扭曲

python - 试图让 Scrapy 进入项目以运行 Crawl 命令