C#深入多线程
主線程:
th = Thread.CurrentThread; //現在的線程為主線程 th.Name = "MainThread"; //set線程名字:主線程本身沒有名字 thread1.Text += th.Name; //get線程名字創建線程:
//創建線程 ThreadStart thread_action = new ThreadStart(ThreadAction); //方法/寫法一 Thread new_thread = new Thread(thread_action); new_thread.Start();new Thread(ThreadAction).Start(); //方法二:自動轉換成ThreadStart new Thread(() => ThreadAction()); //方法三:使用lambda表達式public static void ThreadAction() {Console.WriteLine("New Thread will do."); }創建帶參數的線程:
ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(testBoy); Thread new_thread = new Thread(parameterizedThreadStart); new_thread.Start("hello"); //這樣只能指定一個參數new Thread(testBoy).Start("hello"); new Thread(() => testBoy("hello baby")).Start(); //這start就不要寫參數了,不然會拋出異常的;這樣寫的好處是可以有多個參數static void testBoy(object girl) {Console.WriteLine(girl); }暫停線程:
Thread.Sleep(1000); //讓當前線程sleep,單位ms等待線程(等待與暫停不一樣):
等待:當前線程,等待調用Join的線程執行完畢。暫停:暫停調用Sleep的線程。
銷毀線程(在定義線程引用thread的地方,可以調用thread.Abort方法):
thread.Abort(); //用Thread.ResetAbort();取消當前線程的Abort如果線程已經Start、Abort,再次Start,則會拋出異常System.Threading.ThreadStateException。
判斷線程的狀態:
Console.WriteLine(t.ThreadState); //判斷的是線程的生命周期的狀態;t.IsAlive是執行的狀態線程優先級:
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1); //把所有的線程放在單個CPU上運行(便于測試看到效果) t.Priority = ThreadPriority.Lowest; //可以get、set優先級多個線程操作同一個對象時——加鎖:
static void Main() {Console.WriteLine("Incorrect counter"); //先給出一個不加鎖的,錯誤處理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"); //然后再加鎖進行試驗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();//因為如果不加鎖:假設當前對象的Count是10,那么可能線程1正在+1,得到11,還沒有保存;與此同時線程2也在+1,也得到11。于是最后保存的結果就是11;但是按道理應該是12的 —— 錯誤原因//加了鎖:lock另外一個對象,于是一個線程訪問該對象時,其他線程是無法訪問的,直到該線程訪問完畢 —— 因此不會出現上面的情況 } static void TestCounter(CounterBase c) {for(int i = 0; i < 100000; i++){c.Decrement();c.Increment();} }以上做法,可能會造成死鎖(例如有兩把鎖lock1、lock2:線程1先鎖住了lock1,想要試圖鎖住lock2,卻在此之前先Sleep較長時間,此時線程2趁機鎖住lock2 —— 死鎖產生:因為現在線程2是不能訪問lock1的,如果線程2要訪問lock1,則會等待線程1釋放lock1;然而線程1在釋放lock1之前,會先度過休眠期,然后訪問lock2,但是也不行。故線程1、2都陷入不斷等待的狀態,即死鎖狀態(有一點還不明白,因為是線程,不像進程一樣會分配大量資源,因此死鎖也不會降低太多速度)。用代碼解決死鎖問題(先看下面的代碼,再考慮這些問題):
static void Main() {object lock1 = new object();object lock2 = new object();//為了避免死鎖導致后面的程序無法執行,先使用可以斷開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!");}}//現在直接訪問,肯定就deaLock啦new Thread(() => LockTooMuch(lock1, lock2)).Start();lock(lock2){Thread.Sleep(1000);lock(lock1){Console.WriteLine("Acquired a protected resource successfully");}Console.WriteLine("在前面已經鎖住了,所以后面就不用寫什么else了");} } static void LockTooMuch(object lock1, object lock2) {lock(lock1){Thread.Sleep(1000);lock (lock2) ;} }?
轉載于:https://www.cnblogs.com/quanxi/p/6550559.html
總結
- 上一篇: mvc EF 从数据库更新实体,添加视图
- 下一篇: 数据结构(8)----栈与队列之循环队列