C# 不可变哈希集锁定
C# Immutable HashSet locking
假设服务器存储连接数据的 ImmutableHashSet
ImmutableHashSet<ConnectionData> connections = new ...
然后我收到各种电话 adding/removing/reading,即:
OnConnected(connectionData) => connections = connections.Add(connectionData);
OnDisconnected(connectionData) => connections = connections.Remove(connectionData);
我的问题是,在上述仅对 HashSet (Add/Remove) 执行单个操作的调用中,我应该锁定连接吗?还是 ImmutableHashSet 操作线程安全?
Add
和 Remove
方法调用 return 一个全新的 ImmutableHashSet
。因此,当类型为 thread-safe 时,您将需要使用锁定 - 来处理同时多次调用 Add
或 Remove
的情况。 否则,如果两个 Add
调用同时发生(作为示例),您就会遇到典型的竞争条件。
因此,您需要使用锁对象:
private object lockObject = new lockObject();
然后在分配给 connections
的每个代码块周围使用 lock(lockObject)
(例如,您的 Add
和 Remove
调用)。
另见@Flydog57 提供的精彩link 上述评论
您将值直接分配回集合的模式不是线程安全的。但是,在使用不可变集合时,您通常不希望 lock
。这些集合的主要特征之一是无锁操作,这通常具有更高的性能。相反,使用 ImmutableInterlocked
class:
ImmutableHashSet<ConnectionData> connections;
ImmutableInterlocked.Update(ref connections,
(collection, item) => collection.Add(item),
connectionData);
ImmutableInterlocked.Update(ref connections,
(collection, item) => collection.Remove(item),
connectionData);
假设服务器存储连接数据的 ImmutableHashSet
ImmutableHashSet<ConnectionData> connections = new ...
然后我收到各种电话 adding/removing/reading,即:
OnConnected(connectionData) => connections = connections.Add(connectionData);
OnDisconnected(connectionData) => connections = connections.Remove(connectionData);
我的问题是,在上述仅对 HashSet (Add/Remove) 执行单个操作的调用中,我应该锁定连接吗?还是 ImmutableHashSet 操作线程安全?
Add
和 Remove
方法调用 return 一个全新的 ImmutableHashSet
。因此,当类型为 thread-safe 时,您将需要使用锁定 - 来处理同时多次调用 Add
或 Remove
的情况。 否则,如果两个 Add
调用同时发生(作为示例),您就会遇到典型的竞争条件。
因此,您需要使用锁对象:
private object lockObject = new lockObject();
然后在分配给 connections
的每个代码块周围使用 lock(lockObject)
(例如,您的 Add
和 Remove
调用)。
另见@Flydog57 提供的精彩link 上述评论
您将值直接分配回集合的模式不是线程安全的。但是,在使用不可变集合时,您通常不希望 lock
。这些集合的主要特征之一是无锁操作,这通常具有更高的性能。相反,使用 ImmutableInterlocked
class:
ImmutableHashSet<ConnectionData> connections;
ImmutableInterlocked.Update(ref connections,
(collection, item) => collection.Add(item),
connectionData);
ImmutableInterlocked.Update(ref connections,
(collection, item) => collection.Remove(item),
connectionData);