簡體   English   中英

MailboxProcessor類型是鎖的替代品嗎?

[英]Is the MailboxProcessor type a replacement for locks?

我一直在慢慢研究F#帶來的所有功能。 引起我興趣的是MailboxProcessor

  1. 在C#中相當於這個很可能使用鎖。 我們可以將MailboxProcessor視為鎖的替代品嗎?
  2. 在下面的例子中,我做了什么特別天真的事情,或者你能看到任何可以改進的東西嗎?


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()

郵箱(和類似的結構)用於不使用鎖的編程模型,因為它們本身是圍繞異步處理構建的。 (缺乏共享可變狀態是該模型的另一個要求)。

Actor模型可以被認為是一系列單線程迷你應用程序,它們通過相互發送和接收數據進行通信。 每個迷你應用程序一次只能由一個線程運行。 這與缺乏共享狀態相結合,使鎖定變得不必要。

程序模型(以及大多數OO代碼,其核心是程序性的),使用線程級並發,以及對其他對象的同步調用。 Actor模型翻轉它 - 對象之間的調用(消息)是異步的,但每個對象是完全同步的。

坦率地說,我不太了解F#來真正分析你的代碼。 它確實看起來像你試圖在你的郵箱周圍粘貼一個同步外殼,我想知道這是否真的是最好的事情(完全接受郵箱模型)。 在您的實現中,看起來您確實使用它作為鎖的替代品。

問題的第一部分:

MailboxProcessor類是在其自己的線程上運行的消息隊列。 您可以從任何線程向異步發送消息到MailboxProcessor同步。

這種模型允許通過消息傳遞而不是使用lock / mutexes / ipc mechanics在線程之間進行通信。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM