多線程學習筆記第三篇

來源:互聯網
上載者:User

多線程學習筆記第3篇

  前言:這篇部落客要是在上一篇部落格的基礎上,繼續記錄了死結,線程同步和線程池的一些知識,方便我以後繼續的學習,在這裡貼出來和大家共用一下

1. 對象池技術類比

  (1) 如果一些對象建立非常消耗時間和資源,使用非常頻繁,這時候可以考慮使用對象池技術

  (2)對象池其實就是一個數組,當我們想用一個對象的時候直接從池子裡面取,別的對象也可以從池子裡面取

  (3)使用代碼類比對象池Demo添加鎖

 namespace ObjectPoolPractice     {            class Program            {                   static void Main(string[] args)                   {                          //定義一個對象池                          MyConnection[] pool = new MyConnection[100];                          int index = 0; //當前對象池中對象的個數                          //定義一個鎖對象                          Object objLock = new object();  //可以鎖定字串,但是盡量不要鎖定字串,因為相同的字串指向的引用相同                          //當然也可以鎖定this                          //類比對象池的使用,生產者和消費者的類比                          //類比5個生產者,不停地往對象池裡面添加對象                          for (int i = 0; i < 5; i++)                          {                                 Thread thread = new Thread(() =>                                 {                                        while (true)                                        {                                               //鎖的對象必須是參考型別,因為同步索引塊在堆上的                                               //只有Lock同一個對象才能互斥                                               lock (objLock)//阻塞當前線程,等待拿到當前對象的鎖                                               {                                                      if (index < pool.Length)                                                      {                                                             Console.WriteLine("生產一個對象");                                                             //生產對象,並將對象放到池子裡面去,生產者                                                             MyConnection conn = new MyConnection();                                                             //放到池子裡面                                                             pool[index] = conn;                                                             index++;                                                      }//執行到最後的時候釋放鎖                                                      Thread.Sleep(300);                                               }                                        }                                 });                                 thread.IsBackground = true;                                 thread.Start();                          }                          //類比10個消費者                          for (int i = 0; i < 10; i++)                          {                                 Thread thread = new Thread(() =>                                 {                                        while (true)                                        {                                               lock (objLock)                                               {                                                      if (index > 0)                                                      {                                                             Console.WriteLine("消費一個對象:" + pool[index - 1].ToString());                                                               pool[index - 1] = null;                                                             index--;                                                      }                                                      Thread.Sleep(30);                                               }                                        }                                 });                                 thread.IsBackground = true;                                 thread.Start();                          }                          Console.ReadLine();                   }            }            //假設建立此對象非常消耗時間            public class MyConnection            {              }     }

  (4)資料庫模仿鎖

       1)select * from bank with(nolock) --表示當前表做查詢的時候不加鎖

  (5)解決死結的方法是操作資源的順序一致

2. 線程同步

  (1) 參考上面的案例代碼進行說明

  (2)new在堆上申請記憶體空間後幹了什麼

       1)Object objLock = new object();

       2)開闢記憶體

       3)調用建構函式

       4)同步塊索引(複數)

  (3)Lock(文法糖)

       try

       {

              System.Threading.Monitor.Enter(obj);

       }

      finally

       {

              System.Threading.Monitor.Exit(obj);

       }

  (4)lock這段代碼是怎麼啟動並執行,lock語句根本使用的就是Monitor.Enter和Monitor.Exit,也就是說lock(o)時執行Monitor.Enter(this), 大括弧結束時執行Monitor.Exit(this).他的意義在於什麼呢,對於任何一個對象來說,他在記憶體中的第一部分放置的是所有方法的地址,第二部分放著一個索引,他指向CLR中的SyncBlock Cache地區中的一個SyncBlock.什麼意思呢?就是說,當你執行Monitor.Enter(Object)時,如果object的索引值為負數,就從SyncBlock Cache中選區一個SyncBlock,將其地址放在object的索引中。這樣就完成了以object為標誌的鎖定,其他的線程想再次進行Monitor.Enter(object)操作,將獲得object為正數的索引,然後就等待。直到索引變為負數,即線程使用Monitor.Exit(object)將索引變為負數。

  (5)線程同步解決的問題:解決多個線程同時訪問同一個資源的時候,進行同步。同一個時間,我們的資源只允許一個線程來訪問。

3. 線程池

  (1) 在程式中,如果某個建立某種對象所需要的代價太高,同時這個對象又可以反覆使用,那麼我們往往就會準備一個容器,用來儲存一批這樣的對象。於是乎,我們想要用這種對象時,就不需要每次去建立一個,而直接從容器中取出一個現成的對象就可以了。由於節省了建立對象的開銷,程式效能自然就上升了

  (2)ThreadPool class提供了一個線程池,該線程池可用於發送工作項目、處理非同步 I/O、代表其他線程等待以及處理計時器。 線程池允許在後台運行多個工作,而不需要為每個任務頻繁地建立和銷毀單獨的線程,從而減少了開銷。

  (3)普通的Windows應用程式(如控制台或WinForm/WPF),會將其設定為"處理器數 * 250"。也就是說,如果您的機器為2個2核CPU,那麼CLR線程池的容量預設上限便是1000,也就是說,它最多可以管理1000個線程同時運行

  (4)WaitCallback是一個委託類型,查看源碼是:

       public delegate void WaitCallback(object state);

  (5)線程池Demo

 static void Main(string[] args)   {       Console.WriteLine("主線程是:" + Thread.CurrentThread.ManagedThreadId);       //直接將一個方法教給線程池,線上程池內部的線程閒置時候自動執行當前傳進去的委託方法       for (int i = 0; i < 1000; i++)       {          //一般情況下做非同步都要使用線程池,非常特殊的情況,比如你必須拿到當前線程的執行個體的時候,那麼你可以考慮手動建立線程           //.net很多方面都是用線程池,,比如非同步委託,只要是系統內部幫我們分配的線程都是通過線程池裡面提供的線程            ThreadPool.QueueUserWorkItem(new WaitCallback(DemoWork),"韓迎龍");        }        Console.ReadLine();   }   private static void DemoWork(object state)   {       //這是由線程池來執行的方法       Console.WriteLine("當前執行的方法的線程是:{0}+{1}", Thread.CurrentThread.ManagedThreadId, state); }  //可以執行查看一下,這裡每個人的機器結果可能都不一樣,所以試一下

  (6)線程池支援的最大線程數1023個,預設設定是1000,最小0.

            static void Main(string[] args)        {            int maxThread = 0;            int currentMaxTrhead = 0;            ThreadPool.GetMaxThreads(out maxThread, out currentMaxTrhead); ;            Console.WriteLine("最多線程數是:{0},當前的設定是{1}", maxThread, currentMaxTrhead);           //看最小的和最大的一摸一樣            Console.ReadKey();        }        //執行結果是:最多線程數是:1023,當前的設定是1000

     (7)等待線程執行結束

    static void Main(string[] args)        {            int a = 0;            Thread thread = new Thread(() =>            {                Thread.Sleep(3000);                for (int i = 0; i < 10; i++)                {                    a++;                }                Console.WriteLine("韓迎龍");            });            thread.IsBackground = true;            thread.Start();            Thread.Sleep(1000);            thread.Abort();  //告訴作業系統,將這個線程關閉            thread.Join(); //讓當前線程阻塞,停下來等待thread執行完成            Console.WriteLine(a);            Console.ReadLine();        }

     (8)工作項目

        static void Main(string[] args)        {            //工作項目:比傳統的線程池多了一個傳回值            Task<int> task = new Task<int>(a =>            {                return (int)a;            }, 5);            task.Start();  //調用工作項目執行            Console.WriteLine(task.Result);  //task最好的東西就是能夠擷取到傳回值        }        

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.