📅  最后修改于: 2023-12-03 14:58:17.979000             🧑  作者: Mango
这道题目出自 GATE 2017 Mock Exam II,是一道关于多线程的问题。下面会详细说明题目要求,以及可能的解法。
问题描述:
有两个线程:一号线程负责输出数字 1、3、5……99,二号线程负责输出数字 2、4、6……100。这两个线程应该并发执行,并且保证能够按照从小到大的顺序输出所有的数字。
问题要求:
编写一个程序,使用多线程技术实现上述问题要求。
要求使用一门通用的编程语言实现,且应当按照多线程编程的最佳实践来编写代码。
这个问题看上去很简单,但实际上涉及到的细节有很多。下面我们来分别考虑一下如何实现这个问题:
首先,我们可以使用信号量来实现这个问题:
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()
这里我们利用了两个信号量 sem1
和 sem2
,来控制两个线程之间的交互。sem1
初始值为 1,表示第一个线程可以开始执行,并得到了锁;sem2
初始值为 0,表示第二个线程需要等待第一个线程释放锁之后才能开始执行。
当第一个线程执行完毕输出奇数之后,他释放了 sem2
的锁,此时第二个线程就可以开始执行了,输出偶数,然后再释放锁 sem1
,这样就保证了两个线程执行的顺序。
另外一个解法是使用锁来实现。这里我们可以使用 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
,用来同步两个线程之间的交互。
当第一个线程执行完毕输出奇数之后,他通过条件变量通知第二个线程开始执行,然后自己阻塞等待。当第二个线程执行完毕输出偶数之后,他也通过条件变量通知第一个线程开始执行,然后自己阻塞等待。通过这样的同步方式,就可以保证两个线程按照要求协同执行了。
这道题目考察了多线程编程的基础知识和技巧。编写多线程程序时,我们应当注意线程之间的同步,特别是对于共享资源的使用要格外小心。一些工具类,如信号量、互斥锁、条件变量等,可以方便我们实现同步的目的。