我正在做一个程序,通过每次操作生成一个代理/邮箱处理器,一次处理许多阻塞I / O操作。 我有一堆文件,我已经在一张地图中缓存在内存中,我希望在这些代理中分享这些文件。但是,每当对文件进行更改时,我都会有一个FileSystemWatcher来回调,以便我可以更新缓存。
如何在没有多线程读写错误导致缓存被破坏的情况下实现这一目标?
在我看来,Map已经基于指向对象的指针了,所以这会自动解决我的问题,因为我只是在加载时更改指向新对象的指针,或者这是对它的理解不足?
由于
答案 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
类,它已经实现了可兼容的可读写字典。