基本知识,无参数Thread和带参数的Thread
Thread类的参数就是参数指针,可以传入一个无参的函数。
如果要传入带参数的函数,先new一个ParameterizedThreadStart委托实例,带参数的函数名作为它的参数。带参数的函数必须且只能有一个object参数。参考下面的
ConterWithParam(object param)
static int iCnt = 0; static readonly int N = 10000; static void Main(string[] args) { Thread[] thrs = new Thread[N]; for (int i = 0; i < N; i++) { thrs[i] = new Thread(Counter); thrs[i].Start(); } for (int i = 0; i < N; i++) { thrs[i].Join(); } Console.WriteLine(iCnt); iCnt = 0; ParameterizedThreadStart[] thrsp = new ParameterizedThreadStart[N]; object param = 2; for (int i = 0; i < N; i++) { thrsp[i] = new ParameterizedThreadStart(ConterWithParam); thrs[i] = new Thread(thrsp[i]); thrs[i].Start(param); } for (int i = 0; i < N; i++) { //当NewThread调用Join方法的时候,MainThread就被停止执行,直到NewThread线程执行完毕 thrs[i].Join(); } Console.WriteLine(iCnt); } static void Counter() { Thread.Sleep(100); iCnt++; //Console.WriteLine("finish iCnt++,now iCnt is " + iCnt); } static void ConterWithParam(object param) { Thread.Sleep(100); int i = (int)param; iCnt += i; //Console.WriteLine("finish iCnt+"+i+",now iCnt is " + iCnt); }
该例子输出结果
2)互斥信号灯mutex
第一节的结果是不是有点奇怪。明明加了10000次,结果却是9550.
带参数的那个例子,一次加2,加10000次,应该是20000才对。结果却是19678.
这是因为对全局变量的访问iCnt出现了冲突。比如两个线程同时取到了iCnt=0时的值,同时执行了i++,那么iCnt的最后状态肯定是1,而不是会2。为了让iCnt得到正确的值。
我们引入互斥信号灯。
static int iCnt = 0; static readonly int N = 10000; static Mutex mut = new Mutex(); static void Main(string[] args) { Thread[] thrs = new Thread[N]; for (int i = 0; i < N; i++) { thrs[i] = new Thread(Counter); thrs[i].Start(); } for (int i = 0; i < N; i++) { thrs[i].Join(); } Console.WriteLine(iCnt); iCnt = 0; ParameterizedThreadStart[] thrsp = new ParameterizedThreadStart[N]; object param = 2; for (int i = 0; i < N; i++) { thrsp[i] = new ParameterizedThreadStart(ConterWithParam); thrs[i] = new Thread(thrsp[i]); thrs[i].Start(param); } for (int i = 0; i < N; i++) { //当NewThread调用Join方法的时候,MainThread就被停止执行,直到NewThread线程执行完毕 thrs[i].Join(); } Console.WriteLine(iCnt); } static void Counter() { Thread.Sleep(10); //锁 mut.WaitOne(); iCnt++; //释放 mut.ReleaseMutex(); //Console.WriteLine("finish iCnt++,now iCnt is " + iCnt); } static void ConterWithParam(object param) { Thread.Sleep(10); //锁住 mut.WaitOne(); int i = (int)param; iCnt += i; //释放 mut.ReleaseMutex(); //Console.WriteLine("finish iCnt+"+i+",now iCnt is " + iCnt); }
本次执行结果
3) 同步信号灯Semaphore
用最经典的生产者-消费者来解释。
static Semaphore sem = new Semaphore(0, 1); static Semaphore sem2 = new Semaphore(0, 5); static void Main(string[] args) { Console.WriteLine("消费者等生产者生产一个item"); Thread thConsumer = new Thread(Consume); thConsumer.Start(); Thread thProductor = new Thread(Product); thProductor.Start(); thConsumer.Join(); thProductor.Join(); Console.WriteLine("............................."); Console.WriteLine("多并发的例子....."); for (int i = 0; i < 10; i++) { Thread t1 = new Thread(Consume2); t1.Start(); Thread t2 = new Thread(Product2); t2.Start(); }//end for } static void Product() { Thread.Sleep(2000); Console.WriteLine("Product an item..."); sem.Release(); } static void Consume() { Thread.Sleep(1000); Console.WriteLine("Consumer is waiting an item..."); sem.WaitOne(); Console.WriteLine("Consumer get an item..."); } static void Product2() { Thread.Sleep(1000); Console.WriteLine("Product an item..."); sem2.Release(); } static void Consume2() { Thread.Sleep(1000); Console.WriteLine("Consumer is waiting an item..."); sem2.WaitOne(); Console.WriteLine("Consumer get an item..."); }