多線程在構建大型系統的時候是需要重點關注的一個重要方面
特別是在效率(系統跑得多快?)和性能(系統工作正常?)之間做一個權衡的時候
恰當的使用多線程可以極大的提高系統性能
什麼是線程? 每個正在系統上運行的程序都是一個進程
每個進程包含一到多個線程
進程也可能是整個程序或者是部分程序的動態執行
線程是一組指令的集合
或者是程序的特殊段
它可以在程序裡獨立執行
也可以把它理解為代碼運行的上下文
所以線程基本上是輕量級的進程
它負責在單個程序裡執行多任務
通常由操作系統負責多個線程的調度和執行
什麼是多線程?
多線程是為了使得多個線程並行的工作以完成多項任務
以提高系統的效率
線程是在同一時間需要完成多項任務的時候被實現的
使用線程的好處有以下幾點 ·使用線程可以把占據長時間的程序中的任務放到後台去處理
·用戶界面可以更加吸引人
這樣比如用戶點擊了一個按鈕去觸發某些事件的處理
可以彈出一個進度條來顯示處理的進度
·程序的運行速度可能加快
·在一些等待的任務實現上如用戶輸入
文件讀寫和網絡收發數據等
線程就比較有用了
在這種情況下我們可以釋放一些珍貴的資源如內存占用等等
還有其他很多使用多線程的好處
這裡就不一一說明了
一些線程模型的背景 我們可以重點討論一下在Win
環境中常用的一些模型
·單線程模型
在這種線程模型中
一個進程中只能有一個線程
剩下的進程必須等待當前的線程執行完
這種模型的缺點在於系統完成一個很小的任務都必須占用很長的時間
·塊線程模型(單線程多塊模型STA)
這種模型裡
一個程序裡可能會包含多個執行的線程
在這裡
每個線程被分為進程裡一個單獨的塊
每個進程可以含有多個塊
可以共享多個塊中的數據
程序規定了每個塊中線程的執行時間
所有的請求通過Windows消息隊列進行串行化
這樣保證了每個時刻只能訪問一個塊
因而只有一個單獨的進程可以在某一個時刻得到執行
這種模型比單線程模型的好處在於
可以響應同一時刻的多個用戶請求的任務而不只是單個用戶請求
但它的性能還不是很好
因為它使用了串行化的線程模型
任務是一個接一個得到執行的
·多線程塊模型(自由線程塊模型)
多線程塊模型( MTA )在每個進程裡只有一個塊而不是多個塊
這單個塊控制著多個線程而不是單個線程
這裡不需要消息隊列
因為所有的線程都是相同的塊的一個部分
並且可以共享
這樣的程序比單線程模型和STA的執行速度都要塊
因為降低了系統的負載
因而可以優化來減少系統idle的時間
這些應用程序一般比較復雜
因為程序員必須提供線程同步以保證線程不會並發的請求相同的資源
因而導致競爭情況的發生
這裡有必要提供一個鎖機制
但是這樣也許會導致系統死鎖的發生
多線程在NET裡如何工作? 在本質上和結構來說
NET是一個多線程的環境
有兩種主要的多線程方法是
NET所提倡的
使用ThreadStart來開始你自己的進程
直接的(使用ThreadPool
QueueUserWorkItem)或者間接的(比如Stream
BeginRead
或者調用BeginInvoke)使用ThreadPool類
一般來說
你可以
手動
為長時間運行的任務創建一個新的線程
另外對於短時間運行的任務尤其是經常需要開始的那些
進程池是一個非常好的選擇
進程池可以同時運行多個任務
還可以使用框架類
對於資源緊缺需要進行同步的情況來說
它可以限制某一時刻只允許一個線程訪問資源
這種情況可以視為給線程實現了鎖機制
線程的基類是System
Threading
所有線程通過CLI來進行管理
·創建線程
創建一個新的Thread對象的實例
Thread的構造函數接受一個參數
Thread DummyThread = new Thread( new ThreadStart(dummyFunction) );
·執行線程
使用Threading命名空間裡的start方法來運行線程
DummyThread
Start ();
·組合線程
經常會出現需要組合多個線程的情況
就是當某個線程需要其他線程的結束來完成自己的任務
假設DummyThread必須等待DummyPriorityThread來完成自己的任務
我們只需要這樣做
DummyPriorityThread
Join() ;
·暫停線程
使得線程暫停給定的秒
DummyPriorityThread
Sleep (<Time in Second>);
·中止線程
如果需要中止線程可以使用如下的代碼
DummyPriorityThread
Abort();
·同步
經常我們會遇到需要在線程間進行同步的情況
下面的代碼給出了一些方法
using System;using System
Threading;namespace SynchronizationThreadsExample{
class SynchronizationThreadsExample{
private int counter =
;
static void Main( ) {
SynchronizationThreadsExample STE = new SynchronizationThreadsExample();
STE
ThreadFunction( );
}
public void ThreadFunction ( ) {
Thread DummyThread = new Thread( new ThreadStart(SomeFunction) ;
DummyThread
IsBackground=true;
DummyThread
Name =
First Thread
;
DummyThread
Start( );
Console
WriteLine(
Started thread {
}
DummyThread
Name);
Thread DummyPriorityThread = new Thread( new ThreadStart(SomeFunction) );
DummyPriorityThread
IsBackground=true;
DummyPriorityThread
Name =
Second Thread
;
DummyPriorityThread
Start( );
Console
WriteLine(
Started thread {
}
DummyPriorityThread
Name);
DummyThread
Join( );
DummyPriorityThread
Join( );
}
public void SomeFunction( ) {
try {
while (counter <
) {
int tempCounter = counter;
tempCounter ++;
Thread
Sleep(
);
counter = tempCounter;
Console
WriteLine(
Thread {
}
SomeFunction: {
}
Thread
CurrentThread
Name
counter);
}
}
catch (ThreadInterruptedException Ex) {
Console
WriteLine(
Exception in thread {
}
Thread
CurrentThread
Name);
}
finally {
Console
WriteLine(
Thread {
} Exiting
Thread
CurrentThread
Name);
}
}
}
}
·使用Interlock
C#提供了一個特殊的類叫做interlocked
就是提供了鎖機制的實現
我們可以加入如下的代碼實現鎖機制
Interlocked
SomeFunction (ref counter);
·使用鎖
這是為了鎖定代碼關鍵區域以進行同步
鎖定代碼如下
lock (this){ Some statements ;}
·使用 Monitor
當有需要進行線程管理的時候我們可以使用
Monitor
Enter(this);
其他也有一些方法進行管理
這裡就不一一提及了
線程的缺點 線程自然也有缺點
以下列出了一些
·如果有大量的線程
會影響性能
因為操作系統需要在他們之間切換
·更多的線程需要更多的內存空間
·線程會給程序帶來更多的bug
因此要小心使用
·線程的中止需要考慮其對程序運行的影響
·通常塊模型數據是在多個線程間共享的
需要一個合適的鎖系統替換掉數據共享
From:http://tw.wingwit.com/Article/program/net/201311/13467.html