VB.NET中Shared修饰的SqlComm变量多用户并发访问是否会引发问题
问题分析
Shared变量的行为
VB.NET中Shared修饰的类级别变量属于类本身,而非类的实例,整个应用程序域内所有线程、所有请求共享同一份内存地址的对象实例。
并发场景下的实际表现
当多个用户同时调用NonQuery方法时,会出现以下混乱情况:
- 引用覆盖:每个线程执行到
SqlComm = New SqlCommand(CommandText, SqlConn)这行时,都会直接覆盖全局共享的SqlComm引用。比如线程A刚初始化好自己的命令对象,还没来得及执行,线程B的赋值操作就直接把SqlComm换成了B的命令对象,线程A后续操作的实际是B的命令。 - 执行逻辑错乱:不同线程的命令文本、参数、关联连接会互相串用,导致实际执行的SQL完全不符合当前调用方的预期,轻则查询结果错误,重则出现数据篡改、删除等严重数据事故。
- 运行时异常:
SqlCommand本身不是线程安全类型,多线程同时操作同一个SqlCommand实例(修改属性、执行命令等操作)会直接触发未处理的运行时异常。 - 资源泄漏:每次赋值新的
SqlCommand实例后,旧实例的引用被覆盖,没有被正确调用Dispose释放,会导致非托管资源长期占用,最终引发内存泄漏、数据库连接池耗尽等问题。
结论
这种写法必然会产生严重的并发问题,完全不能用于多线程环境(比如Web应用、多线程桌面应用)。
修复方案
直接删除类级别声明的Shared SqlComm和Shared SqlDA,将这两个对象改为方法内部的局部变量,同时使用Using块自动释放资源,修改后的NonQuery参考代码如下:
Public Shared Function NonQuery(ByVal CommandText As String, _ ByVal ParameterValues As List(Of SqlParameter), _ ByVal CommandType As CommandType) As Integer Dim res As Integer = 0 Using SqlConn As SqlConnection = Connection SqlConn.Open() ' 局部变量,每个线程独立拥有,互不干扰 Using SqlComm As New SqlCommand(CommandText, SqlConn) SqlComm.CommandTimeout = 600 SqlComm.CommandType = CommandType If (ParameterValues IsNot Nothing) Then For Each Parameter In ParameterValues SqlComm.Parameters.Add(Parameter) Next End If res = SqlComm.ExecuteNonQuery() End Using End Using Return res End Function
局部变量存储在线程的调用栈中,每个线程的调用完全独立,不会互相干扰,同时Using块会在代码执行完成后自动释放SqlConnection和SqlCommand的资源,避免泄漏。
内容的提问来源于stack exchange,提问作者rahul nawalkar
相关产品推荐
相关产品推荐

