Leetcode多线程编程:交替打印FooBar Python题解

it2022-05-05  152

首先,要想写出本题,首先先要理解一个概念,就是Semaphore对象

Semaphore()

Semaphore对象内部管理着一个计数器,该计数器由每个acquire()调用递减,并由每个release()调用递增。计数器永远不会低于0,当acquire()发现计数器为0的时候,线程阻塞,等待其他线程调用release()`。

import time import threading def test(): time.sleep(2) print(time.ctime()) for i in range(5): t1=threading.Thread(target=test,args=()) # 实例化一个线程 t1.start() # 启动线程

执行结果:

Thu Jul 18 14:48:01 2019 Thu Jul 18 14:48:01 2019 Thu Jul 18 14:48:01 2019 Thu Jul 18 14:48:01 2019 Thu Jul 18 14:48:01 2019

可以看到,程序在很短时间内生成了5个线程

如果是在主机执行IO密集型任务的时候再执行这种类型的程序时,主机有很大可能因为消耗资源过多而宕机。

这时候就可以为这段程序添加一个计数器功能,来限制一个时间点内的线程数量。

import time import threading s1=threading.Semaphore(5) #添加一个计数器 def test(): s1.acquire() #计数器获得锁,计数器值-1 time.sleep(2) #程序休眠2秒 print(time.ctime()) s1.release() #计数器释放锁,计数器值+1 for i in range(10): t1=threading.Thread(target=test,args=()) #创建线程 t1.start() #启动线程

执行结果:

Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:54 2019 Thu Jul 18 14:55:56 2019 Thu Jul 18 14:55:56 2019 Thu Jul 18 14:55:56 2019 Thu Jul 18 14:55:56 2019 Thu Jul 18 14:55:56 2019

可以看到,由于添加的信号量初始值设定为5,所以线程以每五个进行了“分隔”。

题解

题目描述

提供一个类:

class FooBar { public void foo() { for (int i = 0; i < n; i++) { print("foo"); } } public void bar() { for (int i = 0; i < n; i++) { print("bar"); } } }

两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。

请设计修改程序,以确保 “foobar” 被输出 n 次。

解题思路

使用两个信号量计数器,来对foo函数和bar函数分别加锁。

在调用foo函数的时候,管理foo的信号量计数器foo_lock-1,管理bar的信号量计数器bar_lock+1。 反之,在调用bar函数的时候,管理foo的信号量计数器foo_lock+1,管理bar的信号量计数器bar_lock-1。

题目解答

import threading class FooBar: def __init__(self, n): self.n = n self.foo_lock = threading.Semaphore() #添加信号量计数器,初始值为1 self.foo_lock.acquire() # 令两个计数器的值为0,造成线程阻塞 self.bar_lock = threading.Semaphore() self.bar_lock.acquire() def foo(self, printFoo: 'Callable[[], None]') -> None: for i in range(self.n): # printFoo() outputs "foo". Do not change or remove this line. printFoo() self.bar_lock.release() self.foo_lock.acquire() def bar(self, printBar: 'Callable[[], None]') -> None: for i in range(self.n): self.bar_lock.acquire() # printBar() outputs "bar". Do not change or remove this line. printBar() self.foo_lock.release()

最新回复(0)