我有一个带有一堆序列的F#类。该类包含一个简单的next()
方法,它返回当前序列中的下一个元素。如果已返回当前序列的所有元素,则它将转移到下一个序列。该类包含一个指针,该指针是序列中的下一个元素以及它从哪个序列返回。
我目前仅限于公开next()
方法。
某些上游类将在不同的线程之间使用我的类(相同的对象实例)。这将使得这一点不同步,因为多个线程都应该从头开始。我知道这不是理想的,但这是我现在必须要做的事情。
示例:
Thread 1 next(): return elem. A
Thread 1 next(): return elem. B
Thread 2 next(): return elem. A
Thread 1 next(): return elem. C
Thread 2 next(): return elem. B
有没有办法跟踪每个线程的指针?
我一直在考虑使用Threading.Thread.CurrentThread.ManagedThreadId
作为Map中的键,然后返回指针(并相应地更新它)。我有点担心这个Map的线程安全性,如果两个线程一次更新它们的状态。
我希望somone可以为我提供一些如何让它发挥作用的想法。
答案 0 :(得分:2)
这可以通过使用MailboxProcessor
来管理状态,然后使用类从消费者中抽象MailboxProcessor
来实现。如果您跨多个线程共享实例,他们将以线程安全的方式看到彼此更新。如果您为每个线程使用专用实例,他们将只看到自己的更新。代码就像这样:
// Add whatever other commands you need
type private SequenceMessage = Next of AsyncReplyChannel<int>
type IntSequence() =
let agent = MailboxProcessor<SequenceMessage>.Start
<| fun inbox ->
let rec loop state =
async {
let! message = inbox.Receive()
// Add other matches as requried
match message with
| Next channel ->
let newState = state + 1
channel.Reply(newState)
return! loop newState
}
loop 0
let next () =
agent.PostAndReply <| fun reply -> Next reply
let asyncNext () =
agent.PostAndAsyncReply <| fun reply -> Next reply
member __.Next () = next ()
member __.AsyncNext () = asyncNext ()
然后,要以每个线程从每个其他线程看到更新的方式使用它,您将执行与此相同的操作:
// To share state across multiple threads, use the same instance
let sequence = IntSequence()
[1..10]
|> List.map (fun _ -> sequence.AsyncNext())
|> Async.Parallel
|> Async.RunSynchronously
|> Array.iter (fun i -> printfn "%d" i)
打印哪些:
1
2
3
4
5
6
7
8
9
10
要以每个线程只能看到自己的更新的方式使用它,您只需将上一个示例更改为以下内容:
// To use a dedicate state for each thread, create a new instance
[1..10]
|> List.map (fun _ -> IntSequence())
|> List.map (fun sequence -> sequence.AsyncNext())
|> Async.Parallel
|> Async.RunSynchronously
|> Array.iter (fun i -> printfn "%d" i)
打印哪些:
1
1
1
1
1
1
1
1
1
1