namespace RealitySimulation.Utils.Threading { #region Using directives
using System; using System.Collections.Generic; using System.Text; using System.Threading;
#endregion
/// <summary> /// 同步屏障. /// </summary> public interface ISyncBarrier { /// <summary> /// 获取正在有屏障处理的线程总数. /// </summary> /// <remarks> /// 改变线程总数,是一个同步操作. /// 请在确保没有任何线程使用当前 /// 屏障(或初始化)时改动总数.如果已经有线 /// 程使用屏障,请使用ExchangingThreads /// 异步更改线程的数量. /// </remarks> int TotalThreads { get;set;} /// <summary> /// 获取或者设置等待交换的线程数. /// </summary> /// <remarks> /// 可以通过交换向线程总数中 /// 添加或者删除线程. /// 使用这种方法主要是因为 /// 线程同步过程中,只能在 /// 重建屏障的时候改变线程 /// 总数.而其他时候将造成 /// 同步的失败. /// 此值为正,意味着添加 /// 线程,相反意味着删除 /// 线程. /// 当交换完成,此值自动 /// 置零. /// 此外,如果线程的减少 /// 量大于当前线程总量, /// 直接将总量置零,而不 /// 考虑余量. /// 注意,这是一个异步操作, /// 屏障可能不会立即实现 /// 这个操作.请观察此值, /// 以确定是否进行添加. /// </remarks> int ExchangingThreads { get;set;} /// <summary> /// 获取当前被阻碍的线程数. /// </summary> int BarricadedThreads { get;} /// <summary> /// 穿越屏障. /// </summary> /// <remarks> /// 线程通过调用穿越屏障, /// 将对控制的安排交给屏障. /// 当逃离条件满足,也就是 /// 到达线程数量已经达到 /// 要求的数量,屏障将自动 /// 开放,而线程在此时可以 /// 穿越.当逃离条件尚未满 /// 足,线程将在穿越屏障的 /// 时候被屏障阻塞. /// </remarks> void Stride(); }
public class SyncBarrier:ISyncBarrier { protected int unbarricadedThreads = 0; protected int exchangingThreads = 0;
protected int totalThreads = 0;
public virtual int BarricadedThreads { get { return this.totalThreads - this.unbarricadedThreads; } } public virtual int TotalThreads { get { return this.totalThreads; } set { this.Rebuild(value); } } public virtual int ExchangingThreads { get { return this.exchangingThreads; } set { this.exchangingThreads = value; } }
public SyncBarrier():this(1){} public SyncBarrier(int totalThreads) { this.Rebuild(totalThreads); }
public virtual void Stride() { //Barrier is designed for threads, no thread takes no effect. //And single thread will not be barricaded. if (this.totalThreads > 0) { lock (this) { if (this.unbarricadedThreads > 0) { this.unbarricadedThreads--; //All threads arrived if (this.unbarricadedThreads == 0) { //Rebuild first, then pulse the signal! this.Rebuild(this.totalThreads+this.exchangingThreads); Monitor.PulseAll(this); } else//Not all threads arrived. { Monitor.Wait(this); } //Threads escapes here. } } } }
protected virtual void Rebuild(int totalThreads) { this.unbarricadedThreads = this.totalThreads = totalThreads; this.exchangingThreads = 0; } } }

|