我正在开发一个应用程序,它具有许多可以同时交互的不同实体。我想知道这些实体以线程安全的方式相互交互的最佳方式是什么。
为了用一些简化的代码进行演示,请考虑每个实体都有自己的光纤和一些状态:
class Fiber
{
private ActionBlock<Action> _workQueue;
public Fiber()
{
_workQueue = new ActionBlock<Action>((a) => a());
}
public void Enqueue(Action a)
{
_workQueue.Post(a);
}
public void Stop()
{
_workQueue.Complete();
}
}
class EntityState
{
public int x { get; set; }
}
class Entity
{
private Fiber _fiber = new Fiber();
public EntityState State { get; set; }
// ...
}
假设动作被任意排队到实体纤维上。一个这样的动作可能是一个实体必须修改另一个实体的状态。我考虑过两种选择以线程安全的方式执行此操作。
选项 1:仅允许通过线程安全包装器 IE 进行状态突变
class Entity
{
private Fiber _fiber = new Fiber();
private ReaderWriterLockSlim _stateLock = new ReaderWriterLockSlim();
private EntityState _state = new EntityState();
public T ReadState<T>(Func<EntityState, T> reader)
{
T result = default(T);
_stateLock.EnterReadLock();
result = reader(_state);
_stateLock.ExitReadLock();
return result;
}
public void WriteState(Action<EntityState> writer)
{
_stateLock.EnterWriteLock();
writer(_state);
_stateLock.ExitWriteLock();
}
// ...
}
选项 2:仅通过将状态更改调度到拥有实体的光纤上并返回 Future 来允许状态更改,以便更改器可以看到更改发生的时间,即
class Future<T>
{
public T Value { get; set; }
}
class Entity
{
private Fiber _fiber = new Fiber();
private EntityState _state = new EntityState();
public Future<T> AccessState<T>(Func<EntityState, T> accessor)
{
Future<T> future = new Future<T>();
_fiber.Enqueue(() => future.Value = accessor(_state));
return future;
}
// ...
}
我还没有考虑过哪些其他选择?有没有好的方法来做到这一点?我应该这样做吗?