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

Concurrency F#中多个线程之间的共享列表/映射?,concurrency,f#,Concurrency,F#,我正在编写一个程序,通过为每个操作生成一个代理/MailboxProcessor,一次处理许多阻塞I/O操作。 我在内存中缓存了一堆文件,我想在这些代理之间共享这些文件。但是,我还拥有一个FileSystemWatcher,每当对文件进行更改时都可以回调,这样我就可以更新缓存 我如何做到这一点而不使缓存被多线程读写破坏 在我看来,映射已经基于指向对象的指针,所以这会自动解决我的问题吗?因为我只是在加载新对象时更改指向新对象的指针,还是这是一种错误的理解 谢谢 在我看来,映射已经基于指向对象的指针

我正在编写一个程序,通过为每个操作生成一个代理/MailboxProcessor,一次处理许多阻塞I/O操作。 我在内存中缓存了一堆文件,我想在这些代理之间共享这些文件。但是,我还拥有一个FileSystemWatcher,每当对文件进行更改时都可以回调,这样我就可以更新缓存

我如何做到这一点而不使缓存被多线程读写破坏

在我看来,映射已经基于指向对象的指针,所以这会自动解决我的问题吗?因为我只是在加载新对象时更改指向新对象的指针,还是这是一种错误的理解

谢谢

在我看来,映射已经基于指向对象的指针,所以这会自动解决我的问题吗?因为我只是在加载新对象时更改指向新对象的指针,还是这是一种错误的理解


我认为你的理解是正确的。您可以只对不可变映射进行一个可变引用。向引用写入新映射是原子的,因此无需同步该映射。

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

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

    您的FileSystemWatcherProcess不需要维护文件缓存,它只是盲目地推出消息

  • 您有一个保存映射状态的主进程。File SystemWatcher向主机发送更新。每个子线程都持有对主线程的引用,因此每次处理完一个项目或一批项目时,它们都会向主进程发送一条消息,请求最新的映射


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

根据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)
let updateMap值=
让可变成功=错误
虽然不成功,但你要做什么
让v=!x
让结果=联锁。比较交换(x,v.Add(value),v)

成功谢谢你,听到这个消息我很高兴。但是,我对这个“对不可变映射的可变引用”有点困惑。你会怎么声明呢?@CSkau:
让x=ref(Map.empty)
@Jon:hmmmmm。。。我不确定这种方法。如果一个子线程调用
x:=(!x.add(“Juliet”)
,另一个子线程调用
x:=(!x.add(“Jon”))
同时,有人丢失了他们所做的更改。因此,要么你有一个专用于写的线程,要么你用锁保护多个线程的写操作。即使这样,在没有用锁标记关键部分或将变量声明为volatile的情况下,一些线程可能有一个缓存指针,以防止发生变异g对所有线程都立即可见。最好是完全避免可变状态。但是只有一个写入程序,即
FileSystemWatcher
,对吗?是的,在这种情况下,一次只有一个写入程序。首先是初始加载程序,然后是
FileSystemWatcher
。我主要关心的是其他多个正在加载的线程在这个过程中的任何时候阅读
Map
。在这种情况下,虽然我很幸运只有一个writer,而且我使用的是3.5。但是我不知道有一个并发的集合库。这将在将来非常有用!谢谢。