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

Posted

技术标签:

【中文标题】寻找“工作中的洗碗机”的解决方案【英文标题】:Looking for a solution to "Dishwasher At Work" 【发布时间】:2010-10-21 05:37:04 【问题描述】:

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

虽然可以将脏咖啡杯等放入其中很棒,但您很快就会遇到“盘子的状态如何?”困境。如果你走到厨房,你能从洗碗机里拿盘子,因为它们很干净,只是没有收起来吗?您可以将脏盘子放入洗碗机中吗?否则会使里面的干净盘子失效吗?

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

我的开始选项是在洗碗机上创建一个“干净”和“脏”的翻转标志。当洗碗机清空时,必须切换到“脏”,运行时必须切换到“清洁”。该算法有问题吗?有没有更好/更不容易出错的?

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

【问题讨论】:

你应该尝试让生活更轻松 :-))) 不过好点..非常!!原创 不仅这行得通,还有人打败了我们……amazon.com/Clean-Dirty-Dishwasher-Indicator-255/dp/B00004XSF9 【参考方案1】:

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

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

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

当拿着干净盘子的Dishwasher空了,开始清理另一个Dishwasher里的脏盘子。

此时,User 线程现在可以将脏盘子放入曾经干净​​的 Dishwasher(现在是空的)中。

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

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

注意 2:在 Dishwasher 是单例的受限环境中,提供 KitchenCounterBufferDishwasherOperator 以收起盘子并将脏盘子从 KitchenCounterBuffer 放置到 Dishwasher。然后KitchenCounterBuffer 在上面的算法中扮演脏Dishwasher 的角色。但是,这可能会导致User 线程抛出异常或死亡。

【讨论】:

【参考方案2】:

与编程无关,但它可能有助于回答您的逻辑问题...我的洗碗机有一个“清洁”灯,当您运行洗衣机时会亮起。如果您只是打开门很短时间(即取出一个干净的杯子),灯会保持亮起,但如果您将门打开更长时间(足够时间清空洗衣机),灯就会熄灭。 它并不完美,但它比前面的一面旗帜要可靠得多,必须由(有点健忘的)人来翻转。

【讨论】:

【参考方案3】:

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

只需几个互斥锁就可以解决问题。

你有四种状态。

洗碗机空了,可以放脏盘子 洗碗机脏了,可以放脏盘子 洗碗机正在运行,您不能放入脏盘子或取出干净的盘子。 洗碗机干净,不能放脏盘子,可以取出干净的盘子。

你可以进一步将empty和dirty折叠在一起,因为你不关心区别。

当你想插入一些东西时,你等待 DirtyMutex 当您想开始洗涤时,您可以等待 DirtyMutex 以免浪费水 ;) 清洗结束后,您会发出 CleanMutex 信号 当您想清空洗碗机时,请等待 CleanMutex 当洗碗机空了时,您会发出 DirtyMutex 信号

这假设您可以知道洗碗机何时是空的,如果没有,您将需要 ElementsInDishwasher 的计数信号量,然后再发出 DirtyMutex 信号。

【讨论】:

排长队等待洗碗机完成清洁并不是一个解决办法。 嗯,我不确定我是否从计算的角度理解这一点。如果他们想做其他事情,他们需要投票,没有解决方案。每个“人都可以旋转一个等待线程”并在完成后设置一个值,如果他们愿意,他们可以在内部进行轮询。 对一个资源使用两个不同的互斥锁是有风险的——你要依赖所有的调用者来遵循一个复杂的协议。为什么不是一个保护四态标志的互斥锁? (另请参阅我的答案,在您的答案之后发布。) 当然,“现实世界”的解决方案是拥有两台洗碗机。每个都有相互排斥的状态:一个洗碗机包含干净的盘子,另一个是脏的,它们交替出现。再也不要把盘子收起来了。 @tweakt:是的,详情请看我的回答,:P【参考方案4】:

我喜欢你的类比,但潜在的问题让我担心。以我的经验,一个设计良好的系统总是知道(通常是隐含地)你所指的那种状态。例如,共享资源队列中的资源可供其他进程使用——如果不是,它就不会在队列中。或者,工作线程正在修改的资源处于线程处理所说的任何状态——更重要的是,没有其他线程需要知道它是“干净”还是“脏”。 p>

我还没有遇到(或发明 :-) 的有效设计模式数量之多令人难以置信,但您所描述的内容带有设计气味(或脏盘子)的暗示,而不是有效模式.

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

【讨论】:

问题在于 onDoneWashing 回调处理程序并不总是可靠地实现,因此你不能假设因为那里有盘子它们是脏的【参考方案7】:

看,这就是程序性思维的问题。它将一切都变成了一个批处理过程,这在异步、事件驱动的世界中表现不佳。您需要开始担心状态、线程、竞争条件、持久性等。

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

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

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

【讨论】:

【参考方案8】:

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

这是一个完全不同的架构。对于标准洗碗机,您认为“干净/脏”是洗碗机的一个属性。 “干净”的意思是“没有脏盘子”。对于传送带式洗碗机,“干净/脏”不是洗碗机的属性。

您可能不想切换到此架构,但如果您这样做,请考虑由并发阻塞队列连接的一系列处理对象。一个盘子进入预冲洗器,出来,进入洗衣机,出来,进入烘干机,最后出来。

【讨论】:

【参考方案9】:

您只需要一个标志,正如您所指出的(干净/脏)。洗碗机通常已经提供了这种机制:(物理)锁。

洗碗机开始清空,解锁 洗碗机已解锁,因此可能会将脏盘子放入其中 洗碗机在运行前被锁定 运行后还是锁着,说明里面都是脏的 如果您从中删除了某些内容,但它不是最后一项,则重新锁定它

在软件意义上,锁定仅在于能够将盘子放入洗碗机 - 您会根据是否锁定盘子来知道被移除的盘子是干净还是脏,但只能放一个盘子如果它已解锁。如果你拿走了最后一道菜,你就会解锁它。

【讨论】:

你怎么知道洗碗机什么时候完成? 我假设你知道洗碗机当前是否打开(“如果你走进厨房,你会听到它”),真正的问题是知道餐具何时处于哪种状态洗衣机关了。洗衣机打开时的状态一目了然。【参考方案10】:

对此的一个简单解决方案是保持始终为真的不变量。这样一组不变量的示例可以是:

如果洗碗机是空的/没有完全装满 - 所有的盘子都是脏的 如果洗碗机满了 - 那么所有的盘子都是干净的。

与洗碗机交互的对象的工作是保持这些不变量的顺序。如果有人在洗碗机里加了一个杯子,结果杯子满了,他也必须打开它,这样下一个过来的人会发现洗碗机已经满了,所有的杯子都是干净的。

【讨论】:

这需要洗碗机在完成后完全清空——你不能只取出一个干净的盘子。 人们对什么是“完整”也有不同的看法【参考方案11】:

您可以让洗碗机在其洗涤周期结束时自动弹出它的碗碟吗?

这类似于 Mark Lutton 的想法,类似于将清洁过的盘子推到(可能是临时的)已知清洁盘子队列中,然后可以将它们从队列中取出。

【讨论】:

【参考方案12】:

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

使用可食用的盘子?

【讨论】:

以上是关于寻找“工作中的洗碗机”的解决方案的主要内容,如果未能解决你的问题,请参考以下文章

寻找更pythonic的逻辑解决方案

寻找解决方案的绝对初学者

解决问题第一步:澄清问题之5WHY法寻找根本原因

寻找在 wildfly 上读取standalone.xml 文件的 ansible 解决方案

如何在 JavaScript 中实现决策树。寻找比我丑陋的解决方案更好的解决方案[关闭]

寻找更好的正则表达式解决方案[重复]