C#深入多线程
主線程:
th = Thread.CurrentThread; //現(xiàn)在的線程為主線程 th.Name = "MainThread"; //set線程名字:主線程本身沒有名字 thread1.Text += th.Name; //get線程名字創(chuàng)建線程:
//創(chuàng)建線程 ThreadStart thread_action = new ThreadStart(ThreadAction); //方法/寫法一 Thread new_thread = new Thread(thread_action); new_thread.Start();new Thread(ThreadAction).Start(); //方法二:自動(dòng)轉(zhuǎn)換成ThreadStart new Thread(() => ThreadAction()); //方法三:使用lambda表達(dá)式public static void ThreadAction() {Console.WriteLine("New Thread will do."); }創(chuàng)建帶參數(shù)的線程:
ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(testBoy); Thread new_thread = new Thread(parameterizedThreadStart); new_thread.Start("hello"); //這樣只能指定一個(gè)參數(shù)new Thread(testBoy).Start("hello"); new Thread(() => testBoy("hello baby")).Start(); //這start就不要寫參數(shù)了,不然會(huì)拋出異常的;這樣寫的好處是可以有多個(gè)參數(shù)static void testBoy(object girl) {Console.WriteLine(girl); }暫停線程:
Thread.Sleep(1000); //讓當(dāng)前線程sleep,單位ms等待線程(等待與暫停不一樣):
等待:當(dāng)前線程,等待調(diào)用Join的線程執(zhí)行完畢。暫停:暫停調(diào)用Sleep的線程。
銷毀線程(在定義線程引用thread的地方,可以調(diào)用thread.Abort方法):
thread.Abort(); //用Thread.ResetAbort();取消當(dāng)前線程的Abort如果線程已經(jīng)Start、Abort,再次Start,則會(huì)拋出異常System.Threading.ThreadStateException。
判斷線程的狀態(tài):
Console.WriteLine(t.ThreadState); //判斷的是線程的生命周期的狀態(tài);t.IsAlive是執(zhí)行的狀態(tài)線程優(yōu)先級(jí):
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1); //把所有的線程放在單個(gè)CPU上運(yùn)行(便于測試看到效果) t.Priority = ThreadPriority.Lowest; //可以get、set優(yōu)先級(jí)多個(gè)線程操作同一個(gè)對(duì)象時(shí)——加鎖:
static void Main() {Console.WriteLine("Incorrect counter"); //先給出一個(gè)不加鎖的,錯(cuò)誤處理Counter c = new Counter();Thread t1, t2;t1 = new Thread(() => TestCounter(c));t2 = new Thread(() => TestCounter(c));t1.Start();t2.Start();t1.Join();t2.Join();Console.WriteLine("Total count: {0}", c.Count);Console.WriteLine("-------------------");Console.WriteLine("Correct counter"); //然后再加鎖進(jìn)行試驗(yàn)CounterWithLock c1 = new CounterWithLock();t1 = new Thread(() => TestCounter(c1));t2 = new Thread(() => TestCounter(c1));t1.Start();t2.Start();t1.Join();t2.Join();Console.WriteLine("Total count: {0}", c1.Count);t1.Abort();t2.Abort();//因?yàn)槿绻患渔i:假設(shè)當(dāng)前對(duì)象的Count是10,那么可能線程1正在+1,得到11,還沒有保存;與此同時(shí)線程2也在+1,也得到11。于是最后保存的結(jié)果就是11;但是按道理應(yīng)該是12的 —— 錯(cuò)誤原因//加了鎖:lock另外一個(gè)對(duì)象,于是一個(gè)線程訪問該對(duì)象時(shí),其他線程是無法訪問的,直到該線程訪問完畢 —— 因此不會(huì)出現(xiàn)上面的情況 } static void TestCounter(CounterBase c) {for(int i = 0; i < 100000; i++){c.Decrement();c.Increment();} }以上做法,可能會(huì)造成死鎖(例如有兩把鎖lock1、lock2:線程1先鎖住了lock1,想要試圖鎖住lock2,卻在此之前先Sleep較長時(shí)間,此時(shí)線程2趁機(jī)鎖住lock2 —— 死鎖產(chǎn)生:因?yàn)楝F(xiàn)在線程2是不能訪問lock1的,如果線程2要訪問lock1,則會(huì)等待線程1釋放lock1;然而線程1在釋放lock1之前,會(huì)先度過休眠期,然后訪問lock2,但是也不行。故線程1、2都陷入不斷等待的狀態(tài),即死鎖狀態(tài)(有一點(diǎn)還不明白,因?yàn)槭蔷€程,不像進(jìn)程一樣會(huì)分配大量資源,因此死鎖也不會(huì)降低太多速度)。用代碼解決死鎖問題(先看下面的代碼,再考慮這些問題):
static void Main() {object lock1 = new object();object lock2 = new object();//為了避免死鎖導(dǎo)致后面的程序無法執(zhí)行,先使用可以斷開deadLock的方式new Thread(() => LockTooMuch(lock1, lock2)).Start();lock (lock2){Thread.Sleep(1000);//TryEnter的用法(TryEnter就是try{Enter})Console.WriteLine("Monitor.TryEnter allows not to get stuck, returning false after a specified timeout is elapsed");if(Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5))) //由于上面始終鎖住lock1不放,故這里等多久都只能false {Console.WriteLine("Acquired a protected resource successfully");}else{Console.WriteLine("Timeout acquiring a resource!");}}//現(xiàn)在直接訪問,肯定就deaLock啦new Thread(() => LockTooMuch(lock1, lock2)).Start();lock(lock2){Thread.Sleep(1000);lock(lock1){Console.WriteLine("Acquired a protected resource successfully");}Console.WriteLine("在前面已經(jīng)鎖住了,所以后面就不用寫什么else了");} } static void LockTooMuch(object lock1, object lock2) {lock(lock1){Thread.Sleep(1000);lock (lock2) ;} }?
轉(zhuǎn)載于:https://www.cnblogs.com/quanxi/p/6550559.html
總結(jié)
- 上一篇: mvc EF 从数据库更新实体,添加视图
- 下一篇: C#远程调用技术WebService葵花