假设我在系统中有一个整数列表:
let mutable data: int list = [1; 2; 3; 4; 5]
通过相对 更新(通过添加元素)少数 生产者和消费者 手数的消费者。
注意:如果消费者收到稍微过时的数据也没关系。
同步访问此变量的正确方法是什么?
一个 ) 安全的方法是将此变量包装到代理中并通过序列化消息访问它,我们甚至不需要
mutable
修改器在这里。但是这种方法似乎不是最优的,因为它会不必要地使所有读取访问同步。乙 ) AFAIK 引用分配在 .NET 中是原子的,因此在一个发布者和所有消费者之间,一个简单的分配就足够了:
发布者:
data <- newItem :: data
消费者:
data |> process
那么发布者之间的简单锁定就足以结束这个工作流程?
let monitor = object()
发布者:
lock monitor (fun () -> data <- newItem::data)
我的假设是否正确?哪种方法是首选并且对 F# 更惯用?还有更好的选择吗?
最佳答案
您可以使用 Interlocked.CompareExchange在不显式锁定的情况下处理发布:
let mutable data = [1;2;3;4;5]
let newValue = 0
// To publish:
let mutable tmp = data;
while not(tmp.Equals(Interlocked.CompareExchange(&data, newValue::data, tmp))) do
tmp <- data
如果您有同步的编写器,这可能会带来一点好处。
如果您决定确实希望消费者始终拥有最新数据,请使用
ReaderWriterLockSlim
将允许您完全同步数据,而无需在每次调用时强制读取阻塞。这可能看起来像:
let mutable data = [1;2;3;4;5]
let rwl = ReaderWriterLockSlim()
let newValue = 0
// To publish:
let publish newValue =
rwl.EnterWriteLock()
try
data <- newValue :: data
finally
rwl.ExitWriteLock()
// To read:
let readCurrent =
rwl.EnterReadLock()
try
data
finally
rwl.ExitReadLock()
关于multithreading - F# 同步访问列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23661863/