實習總結:c#開發之旅(三)多線程小結(一)

      由於子系統中的任務,需要處理的數據量比較大,爲了提高系統工作效率,老大要求使用多線程來執行任務,而我剛好負責流程控制這一塊,當時真是被多線程折騰的死去活來,這個系統其實是有原型可以參考的,而且這個原型系統是久經考驗,穩定性也很高;所以老大給我的時間並不多,我當時也沒意識到難度會如此之大,但原型使用的是單線程,很多模塊在單線程下跑得很歡,一到多線程就各種難了。

其實現在想來,使用多線程並行處理數據,真心不算個好的決定。

多線程適合處理的任務性質多爲耗時的等待,或輪詢判斷狀態。而此數據管理系統的瓶頸卻是cpu運算和硬盤數據傳輸速度,後來測試結果也顯示,多線程對性能的提升並不算太明顯。當然這個不是主要原因,如果把系統布在強大的服務器上,性能提升還是有的。

更主要的原因是:數據處理任務太不原子化了(額 不知道原子化的反義詞是什麼),線程安全程度非常低。詳細說明下就是,任務執行的過程中,和太多其他模塊有太多的交互了,而且大量使用了全局變量(比如處理任務需要的各種參數、配置、執行方案)和靜態變量(數據庫操作類的靜態實例),一旦跑起多線程,就各種併發衝突。當時我又沒有很清晰的意識到這個問題,於是到處加鎖,在dal入口加鎖,在任務存取數據的地方加鎖,在使用DBHelper的靜態對象地方加鎖,搞得這部分異常複雜,而且加太多鎖的後果就是性能進一步的下降,搞得幾乎和單線程效率差不多了。

額,說了半天廢話,還沒進入主題,有時間再接着整理(寫)吧。


(待續)

這幾天比較事多,今天有點功夫,接着寫吧,

其實讓線程跑起來倒是不難,


 Thread thread1 = new Thread(delegate())

       {    //功能函數體               });

       thread1.Start();  這是匿名方法創建線程,當然,也可以先實例化delegate。一樣的。

也可以使用 ThreadPool.QueueUserWorkItem(DoDeleteInvoke)的方式。

難就難在 thread的控制上,一般來說,如果要對線程執行的情況進行監控,控制,多使用前者。

比如我需要根據用戶設置,可以隨時對線程進行掛起、恢復和銷燬,基本就只能靠前者的方式了。

最開始的時候,我是檢查ThreadState然後使用Suspended和Resume方法,遇到了很多問題。

//調用Resume方法可以恢復一個被延遲的線程。如果線程沒有被延遲,Resume方法就是無效的。
if (thread.ThreadState = ThreadState.Suspended){
  thread.Resume();
}

引用msdn:

“只在少數幾個調試方案中涉及線程狀態枚舉。您的代碼在任何情況下都不應使用線程狀態來同步線程的活動。”

Thread .Suspend 和 Thread .Resume 方法通常並不是對所有應用程序都有用,並且不應將其與同步機制混淆。 由於 Thread .Suspend 和 Thread .Resume 不依賴於受控制線程的協作,因此,它們極具侵犯性並且會導致嚴重的應用程序問題,如死鎖(例如,如果掛起的線程佔有另一個線程需要的資源,就會發生這種情況)。”

 

 

Thread有個threadState屬性代表了線程的狀態信息

可以通過這個屬性判斷線程當時的狀態,

當一個thread實例剛創建時,他的threadstate是unstarted;當此線程被調用start()啓動之後,他的threadstate是 running; 在此線程啓動之後,如果想讓他暫停(阻塞),能調用thread.sleep()方法,他有兩個重載方法(sleep(int )、sleep(timespan)),只不過是表示時間量的格式不同而已,當在某線程內調用此函數時,他表示此線程將阻塞一段時間(時間是由傳遞給sleep 的毫秒數或timespan決定的,但若參數爲0則表示掛起此線程以使其他線程能夠執行,指定 infinite 以無限期阻塞線程),此時他的threadstate將變爲waitsleepjoin,另外值得注意一點的是sleep()函數被定義爲了static?! 這也意味着他不能和某個線程實例結合起來用,也即不存在類似於t1.sleep(10)的調用!正是如此,sleep()函數只能由需“sleep”的線程自己調用,不允許其他線程調用,正如when to sleep是個人私事不能由他人決定。不過當某線程處於waitsleepjoin狀態而又不得不喚醒他時,可使用thread.interrupt方法 ,他將在線程上引發threadinterruptedexception。

1, ms不推薦通過thread state這個屬性來同步線程,msdn原話:

 重要事項

只在幾個調試方案中涉及線程狀態。始終不應在代碼中使用線程狀態來同步線程活動。

以前我就看到了這句話,但不太明白,今天的深入調試,才發現確實如此,必須要始終注意,cpu的時間片是不可控且不可預知的,所以你也不知道你現在線程的狀態是不是一定如你預料,比如

this._thread.ThreadState==ThreadState.running  很可能就不是你要的結果,可能線程的資源被搶佔,現在處於watersleepjoin狀態, 那麼這句話返回的就是false了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章