我的团队正在 C# 5.0 中使用 async/await 开发一个多线程应用程序。在实现线程同步的过程中,经过多次迭代,我们提出了一个(可能是新颖的?)带有内部锁的新 SynchronizationContext 实现:
- 调用 Post 时:
- 如果可以获取锁,则立即执行委托
- 如果无法获取锁,则委托排队
- 调用发送时:
- 如果可以获取锁,则执行委托
- 如果无法获取锁,则线程被阻塞
在所有情况下,在执行委托之前,上下文将自己设置为当前上下文,并在委托返回时恢复原始上下文。
这是一个不寻常的模式,因为我们显然不是第一个编写这样一个应用程序的人,我想知道:
- 模式真的安全吗?
- 有没有更好的方法来实现线程同步?
这是 SerializingSynchronizationContext 的源代码和GitHub 上的演示。
以下是它的使用方法:
- 每个需要保护的类都创建自己的上下文实例,如互斥锁。
上下文是可等待的,因此可以使用以下语句。
await myContext;
这只会导致方法的其余部分在上下文的保护下运行。
- 类的所有方法和属性都使用这种模式来保护数据。在等待之间,一次只能在上下文上运行一个线程,因此状态将保持一致。当到达等待时,允许下一个调度线程在上下文上运行。
- 如果需要即使使用等待的表达式也可以保持原子性,自定义 SynchronizationContext 可以与 AsyncLock 结合使用。
- 类的同步方法也可以使用自定义上下文进行保护。