Python 多线程程序错误修复

38 阅读2分钟

有一位同学正在准备考试,他在复习历年试题时遇到了一道程序错误修复问题。他无法找出程序的错误所在,因此希望有人能够帮助他。

该程序包含一个错误。需要确定程序的错误类型,并展示如何修复它。

import threading
import time
import random

# the list "data" must contain two values.
# The second must always be equal to the first multiplied by 4

class GeneratorThread(threading.Thread):
    # Thread for generating value pairs
    def __init__(self, data):
        threading.Thread.__init__(self)
        self.data = data

    def run(self):
        while True:
            # Pick a new first number
            num = random.randint(0, 100)
            self.data[0] = num

            # simulate some processing
            # to calculate second number
            time.sleep(1)

            # Place second value into data
            self.data[1] = num * 4
            time.sleep(1)


class ProcessorThread(threading.Thread):
    # Thread for processing value pairs
    def __init__(self, data):
        threading.Thread.__init__(self)
        self.data = data

    def run(self):
        while True:
            # Process current data
            num1 = self.data[0]
            num2 = self.data[1]
            print("Values are %d and %d." % (num1, num2))

            if num2 != num1 * 4:
                print("\tDATA INCONSISTENCY!")

            time.sleep(2)


if __name__ == "__main__":
    data = [1, 4]
    t1 = GeneratorThread(data)
    t2 = ProcessorThread(data)
    t1.start()
    t2.start()

2、解决方案

该程序存在一个条件竞争问题。基本上,在将 data[0] 设置为某个值之前,然后将 data[1] 设置为该值的四倍之间存在一定时间差。

如果第二个线程在这个时间段内进入并检查值,就会发生数据不一致的情况。

我们可以通过使用锁来同步线程,以确保数据始终一致。

import threading
import time
import random

# the list "data" must contain two values.
# The second must always be equal to the first multiplied by 4

class GeneratorThread(threading.Thread):
    # Thread for generating value pairs
    def __init__(self, data):
        threading.Thread.__init__(self)
        self.datamutex = datamutex  # save reference to the mutex.
        self.data = data

    def run(self):
        while True:
            # Pick a new first number
            num = random.randint(0, 100)

            self.datamutex.acquire()  # get the mutex.
            self.data[0] = num

            # simulate some processing
            # to calculate second number
            time.sleep(1)

            # Place second value into data
            self.data[1] = num * 4
            self.datamutex.release()  # release it to allow other thread
            # to run now that data is consistent.
            time.sleep(1)


class ProcessorThread(threading.Thread):
    # Thread for processing value pairs
    def __init__(self, data):
        threading.Thread.__init__(self)
        self.datamutex = datamutex  # save mutex reference.
        self.data = data

    def run(self):
        while True:
            # Process current data
            self.datamutex.acquire()  # lock (can only happen if data consistent).
            num1 = self.data[0]
            num2 = self.data[1]
            self.datamutex.release()  # release it to allow updates.

            print("Values are %d and %d." % (num1, num2))

            if num2 != num1 * 4:
                print("\tDATA INCONSISTENCY!")

            time.sleep(2)


if __name__ == "__main__":
    datamutex = threading.Lock()  # Create the mutex for both threads.
    data = [1, 4]
    t1 = GeneratorThread(data)
    t2 = ProcessorThread(data)
    t1.start()
    t2.start()

通过使用锁来同步线程,我们解决了条件竞争问题,确保了两个线程可以正确地处理数据。