首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell线程通信模式场景

Haskell线程通信模式场景
EN

Stack Overflow用户
提问于 2012-01-03 05:06:17
回答 1查看 873关注 0票数 11

你有两个线程,a和b。线程a在永远循环中,监听阻塞套接字1。线程b也在永远循环中,监听阻塞套接字2。套接字1和套接字2都可能在任意时间返回数据,因此线程a可能永远处于休眠状态,等待数据,而线程b不断从套接字获取数据并继续处理。这就是背景。

现在假设他们需要共享一个字典。当线程a获得一些数据(如果有的话)时,它会在经过一些处理后将一个键值对添加到字典中,然后继续等待更多的数据。当线程b从其套接字接收数据时,它首先查询字典,以查看是否存在与其在继续处理之前接收的数据相关的信息。没有删除字典,只有插入和查询(如果这对最终解决方案有影响,我会很感兴趣)。

在像python或c这样的标准命令式语言中,这很容易做到,只需使字典在两个作用域中都可用,并且只在线程获得锁之后才查询它,所以线程B总是能看到最新的(几乎是)最新的字典。

在Haskell中,我似乎很难想出一个好的模式实现。MVars,一次只能有一项,所以它不可能是线程a放入字典中的,因为可能会发生新的更新,并且在线程b从MVar获取新字典之前,它将无法推送新字典。另一方面,如果线程b使用MVar发送就绪信号"ok!“对于线程a,可能是线程a在其读套接字上休眠,因此它将无法发送回数据,直到其读套接字解锁!也有通道,但这看起来很混乱,因为我必须不断发送新的字典,而线程B将丢弃除最后一个之外的所有字典。

另一种可行的解决方案是简单地将更新发送到通道,并让线程B为自己构造字典。然而,我想知道是否有更好的替代解决方案。

感谢您花时间阅读这个很长的问题!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-01-03 05:27:45

您可以通过以下方式使用MVar

  • 当线程A获得新数据时,它会尝试使用takeMVar获取字典。当成功时,它更新字典并将其放回MVar
  • When线程B获取数据,它尝试使用takeMVar获取字典-在上面的场景中,A很少获得平均而言应该相当快的数据。然后进行查找,并将字典放回原处。

正如哈马尔所指出的,最好不要直接使用takeMVarputMVar,而是将它们分别包装在modifyMVar_中。如果一个线程在使用字典时发生异常,则使用modifyMVar不将MVar留空。

在线程A中,类似于

代码语言:javascript
复制
modifyMVar_ mvar (\dict -> putMVar mvar (insert newStuff dict))

在线程B中,您所需要的只是一个简单的readMVar (再次感谢@hammar指出这一点)。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8705332

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档