using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Threading; namespace 多线程 { class 竞态问题解决 { public static void Main() { StateObject state = new StateObject(); //启动20条线程,共享操作state对象 for (int i = 0; i < 20; i++) { Thread t = new Thread(new SampleThread().RaceCondition); t.Name = i.ToString(); t.Start(state); } //通过结果可以看出,不等于6的情况出现了,这个频率是不定的。 //原因就是在一个线程执行了if( state == 5 )之后,没来得及向下执行,被别的线程抢到了控制权。 //等再次轮到这个线程时,state已经变成了7,所以就出现了竞态问题。。用断言来显示 //解决办法,用lock来锁定操作 1 在SampleThread中将state对象用lock锁定,但是,这是外部操作时锁定 //我们还有一种更好办法,实现更为优雅,就是将StateObject本身设计成一个安全线程的对象 //用一个同步对象,每次操作ChangeState方法时,就锁这个对象,这样只有当一个线程质心完锁定的代码后 //下一个线程才能抢走控制权 } } class StateObject { private int state = 5; private object sync = new object() ; public void ChangeState( int loop ) { lock( sync ) { if (state == 5) { state++; //如果值不是6时,就要执行断言显示 Trace.Assert(state == 6, "结果不为6,出现在" + loop + "次 线程名字:" + Thread.CurrentThread.Name); } state = 5; } } } class SampleThread { public void RaceCondition(object o) { Trace.Assert(o is StateObject, "传入的必须是StateObject类型的参数"); StateObject state = o as StateObject; int i = 0; while (true) { state.ChangeState(i++); } } } }