我正在读一本Python书中关于并行编程的章节.
以下代码基于有关模块threading的示例.
此特定示例的要点是使用threading.Lock().
代码也可以在GitHub上找到here. 没有锁的密码是here.

import threading


class PrimeThread(threading.Thread):

    lock = threading.Lock()

    def __init__(self, n):
        super().__init__()
        self.n = n

    def run(self):
        if self.n < 2:
            with PrimeThread.lock:
                print('▪ That is not an integer greater 1.')
            return
        i = 2
        while i ** 2 <= self.n:
            remainder = self.n % i
            quotient = self.n // i
            if remainder == 0:  # if n is divisible by i
                with PrimeThread.lock:
                    print(
                        f'▪ {self.n} is not prime, '
                        f'because it is {i} * {quotient}.'
                    )
                return
            i += 1
        with PrimeThread.lock:
            print(f'▪ {self.n} is prime.')


my_threads = []

user_input = input('▶ ')

while user_input != 'q':
    try:
        n = int(user_input)  # raises ValueError if string is not integer
        thread = PrimeThread(n)
        my_threads.append(thread)
        thread.start()
    except ValueError:
        with PrimeThread.lock:
            print('▪ That is not an integer.')

    with PrimeThread.lock:
        user_input = input('▶ ')

for t in my_threads:
    t.join()

初始版本的问题在于,输出可能会干扰新的输入:

▶ 126821609265383
▶ 874496478251477▪ 126821609265383 is prime.

▶ ▪ 874496478251477 is not prime, because it is 23760017 * 36805381.

锁应该实现,它看起来是这样的:

▶ 126821609265383
▶ 874496478251477
▪ 126821609265383 is prime.
▪ 874496478251477 is not prime, because it is 23760017 * 36805381.

Maybe it does achieve that. (Hard to test with inputs that allow a fast answer.)
But now the program does not return anything for many inputs with 7 or more digits.
4374553 (prime) sometimes works. But 76580839 (prime) and 67898329 (2953 · 22993) will fail.

如何使用锁来防止输入和输出行的混合,并在计算完成后仍然打印结果?

更笼统地说,我想问一下,是否需要控制台来说明线程和锁的点. 这些也可以通过循环一系列数字来说明吗?
(我可能应该在CodeReview上提到这一点.)


Edit:我刚刚意识到,通过输入一些简单的输入,可以触发缺失的输出.
在这种情况下,程序在输入76580839后停滞.
但输入123后,两个答案都会出现:

trick first attempt

但当然,只有在这个把戏已经存在的情况下,缺失的答案才能被释放.在本例中,当输入123时,126821609265383的计算还没有完成,但过了一会儿,通过输入345来释放它.令人惊讶的是,345的yields 现在停滞不前:

trick second attempt

我的问题不变:
需要更改哪些内容才能使程序针对非轻松输入正常运行?
(它已经在轻松输入方面发挥了作用.)

如上所述:This is an example problem about threading.
素数支票只是一个占位符,用于耗费时间和资源的计算.

推荐答案

做你想做的事是不可能的.当在调用input()之前在主线程中获取锁时,辅助线程无法打印结果,因为它无法获取锁.对于小整数,辅助线程可以打印结果,因为它在主线程try 获取锁之前获取锁.CPython的当前实现在上下文切换发生之前为新创建的线程提供了很短的时间(5ms).

您可以通过在代码的开头添加以下代码来体验此功能.

import sys
sys.setswitchinterval(20) # In seconds

Python相关问答推荐

将每个关键字值对转换为pyspark中的Intramame列

Pandas基于另一列的价值的新列

无法获得指数曲线_fit来处理日期

尽管进程输出错误消息,subProcess.check_call的CalledProcess错误.stderr为无

Python如何让代码在一个程序中工作而不在其他程序中工作

在两极中实施频率编码

如何销毁框架并使其在tkinter中看起来像以前的样子?

如何使用entry.bind(FocusIn,self.Method_calling)用于使用网格/列表创建的收件箱

如何处理嵌套的SON?

Pandas 在最近的日期合并,考虑到破产

Pandas实际上如何对基于自定义的索引(integer和非integer)执行索引

当使用keras.utils.Image_dataset_from_directory仅加载测试数据集时,结果不同

处理(潜在)不断增长的任务队列的并行/并行方法

在Polars(Python库)中将二进制转换为具有非UTF-8字符的字符串变量

如何从.cgi网站刮一张表到rame?

使用密钥字典重新配置嵌套字典密钥名

无法在Docker内部运行Python的Matlab SDK模块,但本地没有问题

如果初始groupby找不到满足掩码条件的第一行,我如何更改groupby列,以找到它?

处理具有多个独立头的CSV文件

具有相同图例 colored颜色 和标签的堆叠子图