【问题标题】:Are 'using' blocks thread safe?“使用”块线程安全吗?
【发布时间】:2015-08-07 05:37:26
【问题描述】:

如果我从多个线程调用一些数据访问方法,我是否需要锁定数据库调用周围的代码以确保一致性,或者下面的 using 语句是原子的?

public static DataRow GetData(Int32 id)
{
    using (SqlConnection con = new SqlConnection(connectionString);)         
    {
        con.Open();
        SqlCommand cmd = ...
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(...)
        cmd.Parameters.Add(...)
        DataTable dt = new DataTable();
        return new SqlDataAdapter(cmd).FillWithRetry(dt, sqlGetEmail.CommandText);
    }
}

我认为一个线程不会影响另一个线程定义的和“正在使用”的连接对象。

【问题讨论】:

  • 你想一次打开一个连接吗?
  • 不,我不介意多连接,只要返回的数据一致即可。
  • 你不更新它怎么可能不一致?
  • 我正在考虑在 cmd.Parameters.Add 语句之间或在 add 和 execute 之间切换线程。

标签: c# multithreading concurrency thread-safety


【解决方案1】:

Using 语句与线程安全(或缺乏)无关

它们只是确保在块结束时调用所用对象的Dispose 方法;但在其他方面相当于手册try..finally Dispose

在这种特殊情况下:由于在每个线程上都打开了一个 连接,因此它是“线程安全的”。它仍然可能不是原子的。数据库或其他共享状态。

【讨论】:

  • @Rob 那在using之外:}
  • 所以,简而言之,上面的代码不是线程安全的,需要在整个主体周围使用 lock(_syncLock) 语句。对吗?
  • @Ryan 它是“线程安全的”,因为使用 SQL Server 提供程序,查询将以线程隔离的方式执行和返回数据。也就是说,执行请求时不会出现与线程相关的“错误”。但它仍然不是原子操作(对应用程序本身或数据库);可能没问题,也可能不行 - 取决于需要什么样的保证。
  • 抱歉 atomic 是一个糟糕的短语,我应该使用“线程安全”或“一致”。如果没有锁定,在语句被原始线程执行之前,一个线程不会覆盖(比如说)其中一个参数的值吗?
  • @Ryan 不...您确实不需要根本不需要锁。
【解决方案2】:

我认为一个线程不会影响另一个线程定义的和“正在使用”的连接对象。

所以我想你担心你的连接的并发访问。 using 语句不是锁。如果您想独占使用连接或您应该使用的任何其他实例:

lock(myConnection)
{
    // your code
}

using 关键字用于描述 here

但我认为这里还有其他误解:。在您的示例中,您的连接是一个局部变量,它在控制流进入您的 GetData 方法时被实例化多次(即使在不同的线程中)。因此,即使控制流多次(并且在不同的线程中)重新进入该方法,也不会使用 shared 连接实例,每次进入该方法都会创建自己的实例。

如果连接实例是一个参数,情况会有所不同。那么你应该担心并发问题,并使用锁。

结论:在您的示例中,您无需担心连接实例的并发访问,也无需使用任何锁定语义。

有趣的是,在您的示例中使用 using 确实是正确的,因为 Connection 是 IDisposable,因此您应该使用 try/finally 或更好地使用其快捷方式:using 关键字对其使用应用确定性处置保护。

【讨论】:

    猜你喜欢
    • 2011-10-24
    • 2020-04-15
    • 2011-08-02
    • 2017-03-12
    • 2012-02-14
    • 2011-07-04
    • 2014-04-26
    • 2012-11-30
    • 2010-12-30
    相关资源
    最近更新 更多