程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> .NET同步與異步之相關背景知識(六),.net背景知識

.NET同步與異步之相關背景知識(六),.net背景知識

編輯:關於.NET

.NET同步與異步之相關背景知識(六),.net背景知識


在之前的五篇隨筆中,已經介紹了.NET 類庫中實現並行的常見方式及其基本用法,當然、這些基本用法遠遠不能覆蓋所有,也只能作為一個引子出現在這裡。以下是前五篇隨筆的目錄:

.NET 同步與異步之封裝成Task(五)

.NET 實現並行的幾種方式(四)

.NET 實現並行的幾種方式(三)

.NET 實現並行的幾種方式(二)

.NET 實現並行的幾種方式(一)

 

話再說回來,這五篇隨筆都屬於《同步與異步》系列。同步與異步、這是一個很大、很籠統的話題,以筆者所學很難將其將其介紹清楚,不過、筆者還是會盡力的。以下是筆者打算在近期介紹的一些知識點(大綱)、當然如果您有更好的意見或建議、歡迎評論留言。

1、與“同步與異步”相關的一些背景知識(即當前隨筆)

  線程上下文、上下文切換、競爭條件(競態條件)、鎖、死鎖。

 

2、鎖(Lock、Monitor、ReaderWriterLockSlim)(預計1-2篇隨筆)

 

3、輕量級的鎖(Interlocked、SpinLock)(預計1篇隨筆)

https://msdn.microsoft.com/zh-cn/library/system.threading.spinlock(v=vs.110).aspx

https://msdn.microsoft.com/zh-cn/library/system.threading.interlocked(v=vs.110).aspx

 

4、WaitHandle家族 (預計2篇隨筆)

https://msdn.microsoft.com/zh-cn/library/system.threading.waithandle(VS.80).aspx

https://msdn.microsoft.com/zh-cn/library/system.threading.semaphoreslim(v=vs.110).aspx

 

5、警惕閉包中的變量捕獲(預計1篇隨筆)

 

6、線程安全的集合(預計1篇隨筆)

 

7、因地制宜——CPU密集型操作和IO密集型操作(預計2篇隨筆、各寫一篇)

 


 


 

 

好了,大綱暫時就先這些了,下面進入該篇隨筆的正文、線程方面的相關背景知識:

 

線程上下文

線程的強大之處、我就不再強調了。如此強大的線程、想要“免費”使用它,似乎是不可能的,就像有句話說的那樣:出來混總是要還的。

Windows中每開辟一個線程、系統都要默認分配一定量的內存空間、其中有一塊內存空間用來保存CPU寄存器中的值,我們把這個內存塊稱為線程上下文。

內存空間中除了寄存器集合之外,還有一部分叫線程棧,線程棧的內存開銷要比寄存器集合的內存開銷大的多。

上下文切換

線程、是程序執行流的最小單元,它就像一個邏輯CPU(或者虛擬CPU)。在系統中多個邏輯CPU(線程)共享計算機中的物理CPU核心(一個CPU可能有多個核心)。

Windows在任何時刻,都只會把一個線程分配給一個CPU核心去運行。被分配的線程運行一個“時間片”長度後,時間片到期,此時Windows會切換上下文。

每次切換上下文,Windows都會做如下操作:

1、將CPU寄存器中的值保存到當前的線程上下文中。2、從現有的線程集合中挑選一個線程。3、將挑選的線程的上下文加載到CPU寄存器中。

上下文切換完成後,CPU會運行所選線程,直到它的時間片到期,然後再次發生上下文切換。Windows大約會30毫秒切換一次線程上下文。

 

事實上、上下文切換對性能的影響可能超乎了你的想象:

線程在運行時,線程所需的代碼和數據都存放在CPU的高速緩存中,這使得CPU不必經常訪問內存RAM(訪問它的速度要比訪問高速緩存的速度慢的多)。

當Windows進行上下文切換後、線程運行所需的代碼和數據,可能不在CPU的高速緩存中,因此CPU必須訪問RAM來填充高速緩存、以恢復CPU的高速運行。

但是,大約30毫秒後,上下文切換再一次發生了。

另外、當一個時間片結束後,如果Widnows決定繼續運行同一個線程,那麼將不發生上下文切換。

線程也可以自主終止其時間片,節省出來的時間、CPU可以用來運行其他線程。

關於 Thread.Sleep   方法、這裡說一下它的三個特殊參數, -1, 0, 1 毫秒。

-1,當前線程將永遠休眠(此參數其實沒有意義,雖然Windows不再調度該線程,但它還是占用著內存)。

0,當前線程放棄了剩余的時間片,促使Windows發生上下文切換。當然此時Windows有可能還會繼續運行當前休眠的線程(沒有相同和更高優先級的線程需要運行的時候)

1,Sleep(0), 是不允許線程優先級較低的線程運行的, 而 Sleep(1) 會強制發生一次上下文切換。

 

競爭條件

假如有以下一行代碼、假定當時 整形變量i的值為 0 :

i = i + 1;

當有兩個線程同時運行該行代碼後,變量i的值變為了1。這時候的結果和預期的值2不一致,這時候我們認為是由於競爭條件引發了安全問題。

引發該問題的原因是:多個線程同時訪問了共享資源。

存在競爭條件的代碼,我們認為是線程不安全的代碼。

 

鎖 和 死鎖

解決競爭條件的典型方案是,獲取共享資源的獨占式訪問特權,而獲取該特權的過程、我們稱之為加鎖。而這個特權、就是鎖。

但是、加鎖和釋放鎖的過程中開銷較大、性能影響較大。還有一類更好的解決方案:原子操作,我有時候也會把它稱為輕量級鎖。

當兩把鎖相互等待對方釋放的時候、我們認為此時發生了死鎖。

 

 

 

隨筆暫告一段落、下一篇隨筆介紹: 鎖(Lock、Monitor、ReaderWriterLockSlim)(預計1-2篇隨筆)

附,Demo : http://files.cnblogs.com/files/08shiyan/ParallelDemo.zip

參見更多:隨筆導讀:同步與異步


(未完待續...)

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved