我一直在慢慢研究 F# 带来的所有功能。 MailboxProcessor
尤其引起了我的兴趣。
- C# 中的等效项很可能会使用锁。我们能否将
MailboxProcessor
视为锁的替代品? - 在下面的例子中,我是在做 任何特别幼稚或可以 你看到任何可能的东西 改善了吗?
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# 的了解还不够,无法真正分析您的代码。看起来您确实在尝试在邮箱周围贴上一个看起来同步的外壳,我想知道这是否真的是最好的做法(相对于完全接受邮箱模型)。在您的实现中,您确实将其用作锁的替代品。
关于concurrency - MailboxProcessor 类型是锁的替代品吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2219355/