gpt4 book ai didi

python - 男女通用浴室 : Threading in Python

转载 作者:太空宇宙 更新时间:2023-11-03 11:17:21 25 4
gpt4 key购买 nike

问题:

男性和女性可以使用男女通用的浴室。

卫生间容量无限大,但男女不能同时使用。

我在执行性别隔离规定时遇到了麻烦。我正在尝试使用“Little Book of Semaphores”中的 LightSwitch 设计模式,但我不明白为什么当男性或女性在浴室时该模式不排除异性。

这不是作业问题。这是我在采访中被轰炸的一个问题。

用户.py:

class User(object):

def __init__(self, cv, sex, line_full_event):
self.cv = cv
self.sex = sex
self.line_full_event = line_full_event

def enter_bathroom(self, bathroom):
with self.cv:
bathroom.enter(self.sex, self.cv)

def leave_bathroom(self, bathroom):
bathroom.leave(self.sex, self.cv)

class Male(User):

def __init__(self, cv, sex, line_full_event):
super(Male, self).__init__(cv, sex, line_full_event)

def go(self, bathroom):
logging.debug("Male queueing up")
self.line_full_event.wait()
super(Male, self).enter_bathroom(bathroom)
super(Male, self).leave_bathroom(bathroom)

class Female(User):

def __init__(self, cv, sex, line_full_event):
super(Female, self).__init__(cv, sex, line_full_event)

def go(self, bathroom):
logging.debug("Female queueing up")
self.line_full_event.wait()
super(Female, self).enter_bathroom(bathroom)
super(Female, self).leave_bathroom(bathroom)

LightSwitch.py​​:

class LightSwitch:

def __init__(self):
self.mutex = Lock()
self.count = 0

def inc(self, cv):
with self.mutex:
self.count += 1
logging.debug("inc-ing! count == %d", self.count)
if self.count == 1:
cv.acquire()


def dec(self, cv):
with self.mutex:
self.count -= 1
logging.debug("dec-ing! count == %d", self.count)
if self.count == 0:
cv.notify_all()
cv.release()

浴室.py

MALE = 1
FEMALE = 0

class Bathroom:

def __init__(self):
self.male_switch = LightSwitch()
self.female_switch = LightSwitch()

def enter(self, sex, cv):
if sex == MALE:
self.female_switch.inc(cv)
elif sex == FEMALE:
self.male_switch.inc(cv)

def leave(self, sex, cv):
if sex == MALE:
self.female_switch.dec(cv)
elif sex == FEMALE:
self.male_switch.dec(cv)

主要.py:

def Main():
logging.basicConfig(format='%(threadName)s, %(asctime)s, %(message)s', datefmt='%M:%S', level=logging.DEBUG)
# create Bathroom
b = Bathroom()
# create whatever threading objects we need
males_can_enter, females_can_enter = get_cvs()
line_full = threading.Event()
for i in range(10):
if random.randint(0,1) == MALE:
# create Male user
user = Male(males_can_enter, MALE, line_full)
else:
# create Female user
user = Female(females_can_enter, FEMALE, line_full)
t = threading.Thread(target=user.go, args=(b,))
t.start()
logging.debug("we're off to the races!")
line_full.set()

def get_cvs():
return (threading.Condition(), threading.Condition())


if __name__ == '__main__':
Main()

输出:

Thread-1, 10:21, Male queueing up
Thread-2, 10:21, Female queueing up
Thread-3, 10:21, Male queueing up
Thread-4, 10:21, Female queueing up
Thread-5, 10:21, Male queueing up
Thread-6, 10:21, Female queueing up
Thread-7, 10:21, Male queueing up
Thread-8, 10:21, Female queueing up
Thread-9, 10:21, Female queueing up
Thread-10, 10:21, Male queueing up
MainThread, 10:21, we're off to the races!
Thread-2, 10:21, inc-ing! count == 1
Thread-3, 10:21, inc-ing! count == 1
Thread-3, 10:21, dec-ing! count == 0
Thread-2, 10:21, dec-ing! count == 0
Thread-5, 10:21, inc-ing! count == 1
Thread-9, 10:21, inc-ing! count == 1
Thread-5, 10:21, dec-ing! count == 0
Thread-9, 10:21, dec-ing! count == 0
Thread-4, 10:21, inc-ing! count == 1
Thread-7, 10:21, inc-ing! count == 1
Thread-4, 10:21, dec-ing! count == 0
Thread-7, 10:21, dec-ing! count == 0
Thread-8, 10:21, inc-ing! count == 1
Thread-10, 10:21, inc-ing! count == 1
Thread-8, 10:21, dec-ing! count == 0
Thread-10, 10:21, dec-ing! count == 0
Thread-1, 10:21, inc-ing! count == 1
Thread-6, 10:21, inc-ing! count == 1
Thread-1, 10:21, dec-ing! count == 0
Thread-6, 10:21, dec-ing! count == 0

最佳答案

首先,我身边没有“Little Book of Sempahores”,30 秒的搜索没有产生任何与“Lightswitch 设计模式”相关的 CS(但有很多关于家居装修的东西)。无论如何,我相信你的代码有点太复杂了。这是我想出的:

import logging, threading, random, time

# Lame enum in case you aren't on Python 3.4.
# FEMALE = 0; MALE = 1
names = ["Female", "Male"]

class User(object):
def __init__(self, sex):
self.sex = sex
self.name = names[sex]

def go(self, bathroom):
logging.debug("%s queueing up" % self.name)

with bathroom.condition:
while not bathroom.is_open(self):
bathroom.condition.wait()

logging.debug("%s entering the bathroom" % self.name)
bathroom.enter(self)
time.sleep(1)

logging.debug("%s leaving the bathroom" % self.name)
bathroom.leave(self)

class Bathroom(object):
def __init__(self):
self.condition = threading.Condition()
self.current_sex = None
self.count = 0

def is_open(self, user):
return self.current_sex is None or self.current_sex == user.sex

def enter(self, user):
assert(self.is_open(user))
self.current_sex = user.sex
self.count += 1

def leave(self, user):
assert(user.sex == self.current_sex)
self.count -= 1
assert(self.count >= 0)

if self.count == 0:
logging.debug("Bathroom is empty. Opening for anyone")
self.current_sex = None
with self.condition:
self.condition.notify_all()

def Main():
logging.basicConfig(format='%(threadName)s, %(asctime)s, %(message)s', datefmt='%M:%S', level=logging.DEBUG)

b = Bathroom()

logging.debug("we're off to the races!")
for i in range(10):
user = User(random.randint(0, 1))
t = threading.Thread(target=user.go, args=(b,))
logging.debug("Starting a thread")
t.start()

if __name__ == '__main__':
Main()

关于多线程部分的一些一般性评论:

  • 整个事情都是基于一个单一的 threading.Condition浴室会记录下来。
  • 任何人都可以在浴室已经分配给他们的性别或没有人的情况下进入。
  • 当浴室清空时,浴室会发出 notify_all让所有等待的人都可以使用浴室。
  • 除了有意义的输出之外,我还添加了一堆 assert 以确保一切按预期工作。

输出:

MainThread, 19:27, we're off to the races!
MainThread, 19:27, Starting a thread
Thread-1, 19:27, Male queueing up
Thread-1, 19:27, Male entering the bathroom
MainThread, 19:27, Starting a thread
Thread-2, 19:27, Female queueing up
MainThread, 19:27, Starting a thread
Thread-3, 19:27, Male queueing up
MainThread, 19:27, Starting a thread
Thread-3, 19:27, Male entering the bathroom
Thread-4, 19:27, Female queueing up
MainThread, 19:27, Starting a thread
Thread-5, 19:27, Female queueing up
MainThread, 19:27, Starting a thread
Thread-6, 19:27, Female queueing up
MainThread, 19:27, Starting a thread
Thread-7, 19:27, Male queueing up
MainThread, 19:27, Starting a thread
Thread-7, 19:27, Male entering the bathroom
Thread-8, 19:27, Female queueing up
MainThread, 19:27, Starting a thread
Thread-9, 19:27, Male queueing up
MainThread, 19:27, Starting a thread
Thread-9, 19:27, Male entering the bathroom
Thread-10, 19:27, Male queueing up
Thread-10, 19:27, Male entering the bathroom
Thread-3, 19:28, Male leaving the bathroom
Thread-1, 19:28, Male leaving the bathroom
Thread-7, 19:28, Male leaving the bathroom
Thread-10, 19:28, Male leaving the bathroom
Thread-9, 19:28, Male leaving the bathroom
Thread-9, 19:28, Bathroom is empty. Opening for anyone
Thread-2, 19:28, Female entering the bathroom
Thread-4, 19:28, Female entering the bathroom
Thread-5, 19:28, Female entering the bathroom
Thread-6, 19:28, Female entering the bathroom
Thread-8, 19:28, Female entering the bathroom
Thread-6, 19:29, Female leaving the bathroom
Thread-5, 19:29, Female leaving the bathroom
Thread-4, 19:29, Female leaving the bathroom
Thread-2, 19:29, Female leaving the bathroom
Thread-8, 19:29, Female leaving the bathroom
Thread-8, 19:29, Bathroom is empty. Opening for anyone

请注意,同一性别的每个人最初是如何涌入浴室的(因为他们可以使用)。每个人离开后,其他性别的每个人都涌向浴室。这会产生两个“波浪”的人(每个波浪需要一秒多一点的时间才能完成,因为那是 sleep 的持续时间。

我还简化了您的一些代码,使线程部分更加清晰,并总体上改进了关注点分离。值得注意的是,我完全删除了 line_full 事件,因为我认为其余代码按预期工作不是必需的。

关于python - 男女通用浴室 : Threading in Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49561634/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com