你沒用過的.net4.0


項目升級到.net 4.0很久了,但很多語法和知識點,還停留在以前的版本的有木有?

今天,我們就一塊來看一下在.net 4.0的環境下我們如何編程的。

先從鎖開始。需要你有一點點操作系統和多線程的基礎哦。

再拉回過去,在處理並發的時候,平日大家都是如何實現一個鎖的呢?

  • Lock

早在1.0時代,就有了Lock關鍵字,我們想實現一個自增長的場景:讓多線程有序的訪問靜態類JingTai的num字段,不發生並發。

public  static class JingTai 

{ 

public static int num = 0; 

} 

class Program 

{ 

static void Main(string[] args) 

{ 

//我們想實現一個場景:

//讓多線程有序的訪問靜態類JingTai的num字段,不發生並發

int d = 23; 

Thread[] thread = new Thread[d]; 

for (int i = 0; i < d; i++) 

{ 

thread[i] = new Thread(new ThreadStart(GaiBianJingTai)); 

thread[i].Start(); 

} 

 

Console.ReadLine();//這一句只是為了查看結果使用

} 

static void GaiBianJingTai() 

{ 

Random r = new Random(); 

int n = r.Next(111, 1111); 

Thread.Sleep(n); 

 

lock (typeof(JingTai))//請注意:如果沒有lock(注釋此行),每次的結果是不確定的,而且可能有重復的

{ 

Console.WriteLine(JingTai.num++); 

} 

} 

} 

 

Lock太簡單了,我們就不贅述了。繼續。。。

  • Monitor

Monitor也可以實現同樣的功能,為共享資源加鎖;他在.Net2.0的時代就已經出現了。

View Code
    public static class JingTai
    {

        public static int num = 0;
         
    }

    class Program
    {

        static void Main(string[] args)
        {

            //我們想實現一個場景:

            //讓多線程有序的訪問靜態類JingTai的num字段,不發生並發

            int d = 23;

            Thread[] thread = new Thread[d];

            for (int i = 0; i < d; i++)
            {

                thread[i] = new Thread(new ThreadStart(GaiBianJingTai));

                thread[i].Start();

            }



            Console.ReadLine();//這一句只是為了查看結果使用

        }

        static void GaiBianJingTai()
        {

            Random r = new Random();

            int n = r.Next(111, 1111);

            Thread.Sleep(n);

            Monitor.Enter(typeof(JingTai));

            Console.WriteLine(JingTai.num++);

            Monitor.Exit(typeof(JingTai));

        }

    }

 

我們來分析一下使用Monitor,他的致命缺陷在於性能:

線程使用Monitor訪問共享的資源時候,如果他不能拿到鎖,線程狀態會有運行轉換為阻塞,只以為着將會進行一個線程上下文的切換。如果每個線程對共享資源的訪問時間很短,比如我們的只是num的值加1,那么使用Monitor必然帶來頻繁的線程上下文的切換,明顯影響到程序運行的性能。

好了,鏡頭拉回現在.net4.0平台,微軟才推出了新的自旋鎖SpinLock。

  • SpinLock

當一個線程需要訪問資源的時候,他調用SpinLock.Enter方法申請獨占鎖,如果不能獲得鎖(此時可能運行於另一個CPU核上的線程正在占有這個資源),當前線程就會空轉若干個時間片,然后等下次時間片輪詢到他的時候,他再嘗試申請這個獨占鎖,在這個過程中該線程一直保持着運行時的狀態哦,不會出現上下文的切換。

View Code
 public class JingTai
    {
        public static int num = 0;
        public int day = 0;
    }
    class Program
    {
        static void Main(string[] args)
        {
            //我們想實現一個場景:
            //讓多線程有序的訪問靜態類JingTai的num字段,不發生並發
            int d = 23;
            Thread[] thread = new Thread[d];
            for (int i = 0; i < d; i++)
            {
                thread[i] = new Thread(new ThreadStart(GaiBianJingTai));
                thread[i].Start();
            }

            Console.ReadLine();//這一句只是為了查看結果使用
        }
        /*
         * 以下是微軟給出的注意事項
         SpinLock 僅當您確定這樣做可以改進應用程序的性能之后才能使用。
         * 另外,務必請注意 SpinLock 是一個值類型(出於性能原因)。
         * 因此,您必須非常小心,不要意外復制了 SpinLock 實例,因為兩個實例(原件和副本)之間完全獨立,這可能會導致應用程序出現錯誤行為。
         * 如果必須傳遞 SpinLock 實例,則應該通過引用而不是通過值傳遞。
         * 不要將 SpinLock 實例存儲在只讀字段中。

         */
        private static SpinLock spin = new SpinLock();//創建一個自旋鎖,注意:他的類型是struct 哦
        static void GaiBianJingTai()
        {
            bool lockTaken = false;
             
            try
            {
                spin.Enter(ref lockTaken);
                Console.WriteLine(JingTai.num++);
            }
            finally
            {
                if (lockTaken)
                    spin.Exit();

            }

        }
    }

對於單核CPU,使用SpinLock的效率和Monitor相比差別不大,,但是在多喝CPU環境下,在合適的場景下使用SpinLock取代Monitor,效率大大的提升。

另外,SpinLock 的所有成員都是線程安全的,可從多個線程同時使用。

下一次我想說說.net4.0才有的多核環境下的並行開發。

出處:http://www.cnblogs.com/angben 歡迎轉載,也請保留這段聲明。謝謝!

好了,今天就說這些,嗯,就這些了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM