MailboxProcessor类型是锁的替代品吗?

时间:2010-02-08 03:18:52

标签: concurrency f# message-passing

我一直在慢慢研究F#带来的所有功能。引起我兴趣的是MailboxProcessor

  1. 在C#中相当于这个很可能会使用锁。我们可以将MailboxProcessor视为锁的替代品吗?
  2. 在下面的例子中,我在做什么 什么特别天真或可以 你看到任何可能的东西 改善?

  3. module Tcp =
        open System
        open System.Collections.Generic
        open System.Net
        open System.Net.Sockets
        open System.Threading    
    
        type SocketAsyncMessage =
            | Get of AsyncReplyChannel<SocketAsyncEventArgs>
            | Put of SocketAsyncEventArgs
            | Dispose of AsyncReplyChannel<MailboxProcessor<SocketAsyncMessage>>
    
        type SocketAsyncEventArgsPool(size:int) =             
            let agent = 
                lazy(MailboxProcessor.Start(
                        (fun inbox ->
                            let references = lazy(new List<SocketAsyncEventArgs>(size))       
                            let idleReferences = lazy(new Queue<SocketAsyncEventArgs>(size))                    
                            let rec loop () = 
                                async {
                                    let! message = inbox.Receive()
                                    match message with
                                    | Get channel -> 
                                        if idleReferences.Value.Count > 0 then
                                            channel.Reply(idleReferences.Value.Dequeue())
                                        else    
                                            let args = new SocketAsyncEventArgs()
                                            references.Value.Add args
                                            channel.Reply args  
                                        return! loop()
                                    | Put args ->
                                        if args = null then
                                            nullArg "args" 
                                        elif references.Value.Count < size then
                                            idleReferences.Value.Enqueue args
                                        else                                       
                                            if not(references.Value.Remove args) then
                                                invalidOp "Reference not found."                                        
                                            args.Dispose() 
                                        return! loop()
                                    | Dispose channel ->
                                        if references.IsValueCreated then
                                            references.Value 
                                            |> Seq.iter(fun args -> args.Dispose())
                                        channel.Reply inbox 
                                }
                            loop())))
    
            /// Returns a SocketAsyncEventArgs instance from the pool.         
            member this.Get () =
                agent.Value.PostAndReply(fun channel -> Get channel)            
            /// Returns the SocketAsyncEventArgs instance to the pool. 
            member this.Put args =
                agent.Value.Post(Put args)
            /// Releases all resources used by the SocketAsyncEventArgsPool.
            member this.Dispose () =
                (this:>IDisposable).Dispose()  
    
            interface IDisposable with
                 member this.Dispose() =
                    if agent.IsValueCreated then
                        (agent.Value.PostAndReply(fun channel -> Dispose channel):>IDisposable).Dispose()
    

2 个答案:

答案 0 :(得分:5)

邮箱(和类似的结构)用于不使用锁的编程模型,因为它们本身是围绕异步处理构建的。 (缺乏共享可变状态是该模型的另一个要求)。

Actor模型可以被认为是一系列单线程迷你应用程序,它们通过相互发送和接收数据进行通信。每个迷你应用程序一次只能由一个线程运行。这与缺乏共享状态相结合,不需要锁定。

程序模型(以及大多数OO代码,其核心是程序性的),使用线程级并发以及对其他对象的同步调用。

表示Actor模型会将其翻转 - 对象之间的调用(消息)是异步的,但每个对象都是完全同步的。

坦白说,我不太了解F#来真正分析你的代码。它确实看起来像你试图在你的邮箱周围粘贴一个同步外壳,我想知道这是否真的是最好的事情(完全接受邮箱模型)。在您的实现中,您似乎确实使用它作为锁的替代品。

答案 1 :(得分:0)

问题的第一部分:

MailboxProcessor类是在其自己的线程上运行的消息队列。您可以发送消息 从任何线程以异步方式同步到MailboxProcessor。

这种模型允许通过消息传递而不是使用lock / mutexes / ipc mechanics在线程之间进行通信。