F#中几个线程之间的共享列表/映射?

时间:2010-06-15 13:54:58

标签: concurrency f#

我正在做一个程序,通过每次操作生成一个代理/邮箱处理器,一次处理许多阻塞I / O操作。 我有一堆文件,我已经在一张地图中缓存在内存中,我希望在这些代理中分享这些文件。但是,每当对文件进行更改时,我都会有一个FileSystemWatcher来回调,以便我可以更新缓存。

如何在没有多线程读写错误导致缓存被破坏的情况下实现这一目标?

在我看来,Map已经基于指向对象的指针了,所以这会自动解决我的问题,因为我只是在加载时更改指向新对象的指针,或者这是对它的理解不足?

由于

3 个答案:

答案 0 :(得分:3)

  

在我看来,Map已经基于指向对象的指针了,所以这会自动解决我的问题,因为我只是在加载时更改指向新对象的指针,或者这是对它的理解不足?

我认为你的理解是正确的。你可以只对一个不可变的Map有一个可变引用。将新映射写入引用是原子的,因此不需要同步它。

答案 1 :(得分:1)

当我看到类似的Erlang程序时,系统设置如下:

  • 您可以使用MailboxProcessor包装FileSystemWatcher,这样您就可以将传入的更新作为消息而不是Windows事件处理。您的FileSystemWatcherProcess可以包含正在侦听的子项列表,并根据需要推出更新。这与基于事件的编程基本相同,只是对消息和演员而言。

    你的FileSystemWatcherProcess不需要维护你的文件缓存,它只是盲目推送消息。

  • OR 您有一个包含地图状态的主进程。文件SystemWatcher将更新发送给主服务器。每个子线程都包含对主数据库的引用,因此每次它们完成处理一个项目或一批项目时,它们都会向主进程发送一条消息,请求最新的地图。

两个系统都不需要任何锁定。

答案 2 :(得分:0)

跟随Jon的回答。如果您最终拥有多个编写器,那么您可以始终执行CAS:

而不是锁定
 let updateMap value =
    let mutable success = false
    while not success do
      let v = !x
      let result = Interlocked.CompareExchange(x, v.Add(value), v)
      success <- Object.ReferenceEqual(v, result)

而且,如果只针对.Net 4.0是一个选项,你不应该自己发明所有这些东西:有一个System.Collections.Concurrent.ConcurrentDictionary类,它已经实现了可兼容的可读写字典。