ManualResetEvent类,用于通知一个或多个正在等待的线程已发生事件,它有2种状态:有信号(true)的无信号(false)。
有2种方法可以设置它的信号状态:构造函数构造的时候设置或者通过对象方法设置:
ManualResetEvent mutex=new ManualResetEvent(true/false);//初始化一种状态 mutex.Reset();//设置mutex为无信号 mutex.Set();//设置mutex为有信号
多线程同步控制例子:
namespace BankTransfering2 { class Bank { private double account1 = 2500; private double account2 = 1000; ManualResetEvent[] mres = { new ManualResetEvent(false), new ManualResetEvent(false) }; //创建包含两个ManualResetEvent类对象的数组 public void transfering() //将100元从帐户account1转到帐户account2 { mres[0].Reset(); account1 = account1 - 100; Thread.Sleep(100); account2 = account2 + 100; mres[0].Set(); } public void transfering2() //将300元从帐户account2转到帐户account1 { mres[1].Reset(); account1 = account1 + 300; Thread.Sleep(200); account2 = account2 - 300; mres[1].Set(); } public void querying() //查询帐户account1和account2上的余额 { mres[0].WaitOne();//等待transfering的信号 mres[1].WaitOne();//等待transfering2的信号 //只有当2个信号都为true时,说明它们都运行完了,这个时候query才运行 //WaitHandle.WaitAll(mres); Console.WriteLine("帐户account1上的余额为:{0} 元", account1); Console.WriteLine("帐户account2上的余额为:{0} 元", account2); } } class Program { static void Main(string[] args) { Bank a = new Bank(); Thread user1 = new Thread(new ThreadStart(a.transfering)); //转帐用户1 Thread user2 = new Thread(new ThreadStart(a.transfering2)); //转帐用户2 Thread user3 = new Thread(new ThreadStart(a.querying)); //查账用户 user1.Start(); //执行转帐(account1到account2) user2.Start(); //执行转帐(account2到account1) user3.Start(); //查账用户 Console.ReadKey(); } } }
account1要向account2转钱,transfering是1转向2,transfering2是2转向1。query是查询两人账户状态。
三条线程并发执行的时候,查询操作必须要等transfering和transfering2都没有在执行动作的时候才能准确查到账户余额,transfering和transfering2在执行操作的时候对相应的信号量置为false,执行完动作后又将其置为true。而query必须要等两个信号量为true的时候才能执行(信号量改变的时候会有机制唤醒正在等待的线程,我猜的.....)