寻找“洗碗机在工作”的解决方案

时间:2009-04-22 21:55:14

标签: resource-management

我正在寻找适用于“洗碗机工作”问题的算法。

虽然能够将脏咖啡杯等放入其中是很棒的,但您很快就会遇到“菜肴状态如何?”困境。如果你走到厨房,你可以从洗碗机中取出菜肴,因为它们很干净而且没有放好吗?你可以把一个脏盘放在洗碗机里,还是会使干净的盘子无效?

这似乎是一个必须具有编程等效的问题。您有一个异步触发的共享进程,并将对象从一个状态移动到另一个状态。您需要能够在任何给定时间知道对象的状态。可以应用哪些算法?

我的开始选择是在洗碗机上创建一个“清洁”和“脏”的翻转标志。当洗碗机清空时,必须将其切换为“脏”,当它运行时必须切换到“清洁”。这个算法有问题吗?是否有更好/更少错误?

注意:请不要使用轮询时间表的算法......

12 个答案:

答案 0 :(得分:6)

User线程想要将脏Dish放入干净的洗碗机中时,会出现问题中的主要问题。

解决方案很简单。创建另一个Dishwasher对象。

一个Dishwasher拿着脏盘子,等待清理它们,另一个拿着最近洗过的盘子。

当持有干净餐具的Dishwasher为空时,开始清洁另一个Dishwasher中的脏盘子。

此时,User个线程现在可以将脏菜放入干净的Dishwasher(现在为空)。

继续无限期地交替使用两个Dishwashers的角色。 User线程总是可以放弃脏盘而不需要KitchenCounterBuffer

注意:此解决方案无法解决杯子饥饿问题。 User线程仍然可能阻止等待洗碗机完成清洁。

注意2:在Dishwasher为单身的受限制环境中,提供KitchenCounterBuffer以及DishwasherOperator来收集餐具并将KitchenCounterBuffer的脏菜放入DishwasherKitchenCounterBuffer然后在上面的算法中扮演脏Dishwasher的角色。但是,这可能会导致User个线程抛出异常或死亡。

答案 1 :(得分:2)

没有编程相关但它可能有助于解答您的逻辑问题...我的洗碗机有一个“清洁”灯,当你运行洗衣机时会出现。如果您只是短时间打开门(即取出一个干净的杯子),灯会一直亮着,但是如果您长时间打开门(有足够的时间清空洗衣机),灯会熄灭。 它并不完美,但它比前面的旗帜更可靠,必须被(有点健忘的)人类翻转。

答案 2 :(得分:1)

我假设洗碗机中的所有物品必须干净或脏,但不能混合搭配。下面的解决方案强制执行该属性。如果没有,你的比喻就不太对了。

只需要几个互斥量即可。

你有四种状态。

  • 洗碗机空了,你可以放脏盘子
  • 洗碗机脏了,你可以放脏盘子
  • 洗碗机运行时,不能放脏盘子或取出干净的盘子。
  • 洗碗机清洁,你不能放脏盘子,可以去掉干净的。

你可以进一步折叠空虚和肮脏,因为你不关心差异。

  • 如果您要插入某些内容,请等待DirtyMutex
  • 当您想要开始洗涤时,您需要等待DirtyMutex,这样您就不会浪费水;)
  • 洗涤结束后,您会发出CleanMutex信号
  • 当您要清空洗碗机时,请等待CleanMutex
  • 当洗碗机为空时,您会发出DirtyMutex信号

这假设您可以知道洗碗机什么时候是空的,如果没有,您需要在发信号DirtyMutex之前等待的ElementsInDishwasher的计数信号量。

答案 3 :(得分:1)

我喜欢你的比喻,但潜在的问题让我担心。根据我的经验,精心设计的系统总是知道(通常含蓄地)你所指的那种状态。例如,共享资源队列中的资源可供其他进程使用 - 如果不是,则不会在队列中。或者,由工作线程修改的资源处于线程处理所处的任何状态 - 更重要的是,没有其他线程需要来知道它是“干净”还是“脏”。

有一些令人难以置信的有效设计模式,我还没有遇到(或发明:-),但你所描述的有设计气味(或脏菜)的暗示,而不是有效的模式

答案 4 :(得分:1)

也许Finite State Machine符合您要解决的问题?

答案 5 :(得分:1)

只是制定一个规则,总是从洗碗机中取出干净的餐具,所以任何脏的东西都可以添加更多

答案 6 :(得分:1)

看,这是程序性思维的问题。它将一切都变成了一个批处理过程,而这在异步的,事件驱动的世界中并不能很好地发挥作用。你需要开始担心状态,线程,竞争条件,持久性等等。

避免这些问题的解决方案是让所有菜肴都不可变。如果你需要一个脏盘子,你只需创建一个带有污垢的新实例。

如果获得一个干净的菜肴副本是一种常见的操作(听起来就像你的情况),你可以在Dish对象中添加一个.AsClean()方法,它会自动为你返回一个干净的克隆。如果性能成为瓶颈,如果实例已经清理,可以通过返回this来优化。

当然,这假设您处于具有合理堆空间和自动垃圾收集的环境中。

答案 7 :(得分:1)

我见过商用洗碗机通过隧道在传送带上送菜。你把脏盘子放在左边的架子上。你从右边的架子上取出干净的盘子。单个盘子的清洁/脏污状态与其在机器内的物理位置相对应。

这是一个完全不同的架构。使用标准洗碗机,您会将“清洁/脏”视为洗碗机的属性。 “清洁”意味着“不含脏菜”。使用传送式洗碗机,“清洁/脏”不是洗碗机的属性。

您可能不想切换到此体系结构,但如果这样做,请考虑通过并发阻塞队列连接的一系列处理对象。一道菜进入预冲洗机,出来,进入洗衣机,出来,进入烘干机,然后出来。

答案 8 :(得分:0)

您只需要一个标志,如您所示(清洁/脏)。洗碗机通常已经提供了这种机制:(物理)锁定。

  • 洗碗机开空,解锁
  • 洗碗机已解锁,因此可能会将脏盘子放入其中
  • 在运行洗碗机之前,它已锁定
  • 跑步后,它仍然被锁定,表明里面的一切都很脏
  • 如果您从中删除了某些内容,并且它不是最后一项,则重新锁定它

从软件的角度来说,锁只是能够将餐具放入洗碗机中 - 你知道根据它是否被锁定而被移除的菜是干净还是脏,但只能放一个菜如果它解锁了如果你拿最后一道菜,你就解锁了。

答案 9 :(得分:0)

对此的一个简单解决方案是维护始终为真的不变量。这种不变量集的一个例子可以是:

  • 如果洗碗机是空的/没有完全充满 - 所有餐具都很脏
  • 如果洗碗机已满 - 那么所有餐具都是干净的。

对象的工作是与洗碗机交互以使这些不变量保持有序。如果有人在洗碗机中加入一个杯子并使其充满,他也必须将其打开,以便下一个到处的人会发现洗碗机已经满了,所有的杯子都是干净的。

答案 10 :(得分:0)

在洗涤周期结束时,您是否可以让洗碗机自动弹出餐具?

这与Mark Lutton的想法相似,类似于将清洁过的菜肴推到已知清洁餐具的(可能是临时的)队列中,然后可以将它们出列。

答案 11 :(得分:0)

这是因使用衰减技术而产生的设计问题 - 通过将设计的一部分更新为更高级的形式,您可以摆脱整个问题并节省时间,水和能源。

使用可食用的盘子?