比如说我在一个线程中对这个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 aNumber + bNumber;
//C++: return a>Number + b>Number;
}
原因在于a和b虽然是函数的内部变量没错但aNumber和bNumber却不是它们不存在于堆栈上而是在托管堆上可能被其他线程更改
但只使用局部变量的函数在NET类库中是很少的但NET类库中还是有那么多线程安全的函数是为什么呢?
因为即使一个函数使用了共享资源如果其所使用的共享资源都是线程安全的则这个函数也是线程安全的
比如说这样的函数
private const string connectionString =
…
;public string GetConnectionString()
{
return connectionString;
}
虽然这个函数使用了一个共享资源connectionString但因为这个资源是线程安全的所以这个函数还是线程安全的
同样的我们可以得出如果一个函数只调用线程安全的函数只使用线程安全的共享资源那么这个函数也是线程安全的
这里有一个容易被忽略的问题运算符并不是所有的运算符(尤其是重载后的运算符)都是线程安全的
[] [] []