比如說我在一個線程中對這個connection調用了Open方法然後進行查詢操作但在同一時刻另一個線程調用了Close方法這時候就出現錯誤了
但單純的使用connection而不使用其任何成員比如說if ( connection != null )這樣的代碼是不存在線程沖突的
線程安全的資源其實還有很多在此不一一贅述
對於NET Framework的類型的成員來說只讀的字段是線程安全的
那麼對於屬性和方法來說怎麼知道是不是線程安全的?
三線程安全的函數
因為屬性和方法都是函數組成的所以我們探討一下什麼是線程安全的函數
上面我們說到線程沖突的必要條件是多線程和共享資源那麼如果一個函數裡面沒有使用任何可能共享的資源那麼就不可能出現線程沖突也就是線程安全的比如說這樣的函數
public static int Add( int a
int b ){
return a + b;
}
這個函數中所使用的所有的資源都是自己的局部變量而函數的局部變量是儲存在堆棧上的每個線程都有自己獨立的堆棧所以局部變量不可能跨線程共享所以這樣的函數顯然是線程安全的
但值得注意的是下面的函數不是線程安全的
public static void Swap( ref int a
ref int b )//C++: void Swap( in& a
int& b )
{
int c = a;
a = b;
b = c;
}
因為ref的存在使得函數的參數是按引用傳遞進來的換言之a和b看起來是函數的局部變量但實際上卻是函數外面的東西如果這兩個東西是另一個函數的局部變量倒也沒有問題如果這兩個東西是全局變量(靜態成員)就不能確保沒有線程沖突了而在上個例子中a和b在傳入函數之時就做了一個拷貝的動作所以傳進來的ab到底是全局變量還是靜態成員都沒有關系了
同樣這樣的函數也不是線程安全的
public static int Add( INumber a
INumber b )//C++: int Add( INumber* a
INumber* b );
{
return a
Number + b
Number;
//C++: return a
>Number + b
>Number;
}
原因在於a和b雖然是函數的內部變量沒錯但aNumber和bNumber卻不是它們不存在於堆棧上而是在托管堆上可能被其他線程更改
但只使用局部變量的函數在NET類庫中是很少的但NET類庫中還是有那麼多線程安全的函數是為什麼呢?
因為即使一個函數使用了共享資源如果其所使用的共享資源都是線程安全的則這個函數也是線程安全的
比如說這樣的函數
private const string connectionString =
…
;public string GetConnectionString()
{
return connectionString;
}
雖然這個函數使用了一個共享資源connectionString但因為這個資源是線程安全的所以這個函數還是線程安全的
同樣的我們可以得出如果一個函數只調用線程安全的函數只使用線程安全的共享資源那麼這個函數也是線程安全的
這裡有一個容易被忽略的問題運算符並不是所有的運算符(尤其是重載後的運算符)都是線程安全的
[] [] []
From:http://tw.wingwit.com/Article/program/net/201311/15564.html