📜  门| GATE 2017 MOCK II |问题2(1)

📅  最后修改于: 2023-12-03 14:58:17.979000             🧑  作者: Mango

门| GATE 2017 MOCK II |问题2

这道题目出自 GATE 2017 Mock Exam II,是一道关于多线程的问题。下面会详细说明题目要求,以及可能的解法。

题目要求

问题描述:

有两个线程:一号线程负责输出数字 1、3、5……99,二号线程负责输出数字 2、4、6……100。这两个线程应该并发执行,并且保证能够按照从小到大的顺序输出所有的数字。

问题要求:

编写一个程序,使用多线程技术实现上述问题要求。

要求使用一门通用的编程语言实现,且应当按照多线程编程的最佳实践来编写代码。

解法分析

这个问题看上去很简单,但实际上涉及到的细节有很多。下面我们来分别考虑一下如何实现这个问题:

解法 1:使用信号量

首先,我们可以使用信号量来实现这个问题:

from threading import Semaphore

# 两个线程的信号量
sem1 = Semaphore(1)
sem2 = Semaphore(0)

# 线程 1,输出奇数
def thread_1():
    for i in range(1, 100, 2):
        sem1.acquire()
        print(i)
        sem2.release()

# 线程 2,输出偶数
def thread_2():
    for i in range(2, 101, 2):
        sem2.acquire()
        print(i)
        sem1.release()

# 启动线程
t1 = threading.Thread(target=thread_1)
t2 = threading.Thread(target=thread_2)
t1.start()
t2.start()

# 等待线程结束
t1.join()
t2.join()

这里我们利用了两个信号量 sem1sem2,来控制两个线程之间的交互。sem1 初始值为 1,表示第一个线程可以开始执行,并得到了锁;sem2 初始值为 0,表示第二个线程需要等待第一个线程释放锁之后才能开始执行。

当第一个线程执行完毕输出奇数之后,他释放了 sem2 的锁,此时第二个线程就可以开始执行了,输出偶数,然后再释放锁 sem1,这样就保证了两个线程执行的顺序。

解法 2:使用锁

另外一个解法是使用锁来实现。这里我们可以使用 threading.Lock()threading.Condition()

from threading import Thread, Lock, Condition

# 定义互斥锁和条件变量
mut = Lock()
cond = Condition()

# 共享的数字
num = 1

# 线程 1,输出奇数
def thread_1():
    global num
    while num < 100:
        with mut:
            if num % 2 == 0:
                cond.wait()
            print(num)
            num += 1
            cond.notify()

# 线程 2,输出偶数
def thread_2():
    global num
    while num <= 100:
        with mut:
            if num % 2 == 1:
                cond.wait()
            print(num)
            num += 1
            cond.notify()

# 启动线程
t1 = Thread(target=thread_1)
t2 = Thread(target=thread_2)
t1.start()
t2.start()

# 等待线程结束
t1.join()
t2.join()

这里我们使用了一个共享变量 num,来保存当前要输出的数字。两个线程通过共享这个变量来同步输出数字。我们还定义了一个条件变量 cond,用来同步两个线程之间的交互。

当第一个线程执行完毕输出奇数之后,他通过条件变量通知第二个线程开始执行,然后自己阻塞等待。当第二个线程执行完毕输出偶数之后,他也通过条件变量通知第一个线程开始执行,然后自己阻塞等待。通过这样的同步方式,就可以保证两个线程按照要求协同执行了。

总结

这道题目考察了多线程编程的基础知识和技巧。编写多线程程序时,我们应当注意线程之间的同步,特别是对于共享资源的使用要格外小心。一些工具类,如信号量、互斥锁、条件变量等,可以方便我们实现同步的目的。