【问题标题】:C#.net lock object in one mthod and no lock in another methodC#.net 在一种方法中锁定对象,在另一种方法中没有锁定
【发布时间】:2013-02-15 11:25:46
【问题描述】:

我有两种方法“ExecuteNoQuery”(执行 dbCommand.ExecuteNonQuery())和“Query”执行(dbCommand.ExecuteReader())。 这两种方法都使用相同的连接对象。在 ExecuteNoQuery 方法中实现了一个锁(使用连接对象)和 Query 方法实现了无锁。如果有多个线程,不同的线程同时访问这两个方法,会发生什么?

注意:在 Query 方法中,自定义连接池是使用相同的对象实现的。

public int ExecuteNoQuery(string sqlquery, Hashtable htData) {
try {
 lock(Myservice.dbcon)  
  {
    using (OracleCommand dbCommand = new OracleCommand(sqlquery, Myservice.dbcon)) 
        {

              int rowCount = dbCommand.ExecuteNonQuery();
              return 1;
        }
  }
}


public OracleDataReader Query(string sqlquery, Hashtable htData)
    {
        try
        {
            OracleDataReader dbReader = null;
            Random ran = new Random();
            int randomnumber = ran.Next(1,5);

           Myservice.dbcon = (OracleConnection) Myservice.htdbcon
           ["Connection_" +randomnumber];

            if (Myservice.dbcon.State != System.Data.ConnectionState.Executing 
              || Myservice.dbcon !=  System.Data.ConnectionState.Fetching)
                {
                    using (OracleCommand dbCommand = new OracleCommand(sqlquery,
                     Myservice.dbcon))
                    { 

                        dbReader = dbCommand.ExecuteReader();
                    }
                }
                return dbReader;

        }

【问题讨论】:

    标签: c# object static locking


    【解决方案1】:

    这两种方法都使用相同的连接对象。

    由于一种方法使用锁而另一种方法不使用:不好的事情。对于这种情况,对象不做任何保证,因此您应该期望它以有趣的方式失败。您应该在两个地方使用相同的锁对象,或者更好:只使用隔离代码中的连接,而不是共享连接。使用连接池,在某处拥有共享连接对象很少有用。更合适的模式通常是在需要时获取连接,然后将其释放。如果底层提供程序支持池,这将在理想情况下执行,没有任何同步问题,并允许并行查询等。例如:

    using (var conn = SomeUtilityClass.GetOpenConnection())
    using (var cmd = conn.CreateCommand()) 
    {
        cmd.CommandText = sqlquery;
        int rowCount = dbCommand.ExecuteNonQuery();
        return 1;
    }
    

    而且,重要的是,Query 方法中做同样的事情;没有锁,没有全局共享连接。

    顺便说一句,我也会担心缺少参数。这表明您正在接受 SQL 注入错误。

    【讨论】:

    • 我的应用程序很少遇到挂起的情况。当分析日志时,我发现挂起是由于同时访问这两种方法。它不会给出任何异常(C#/Oracle)。知道挂起的原因是什么吗?
    • @user2075249 因为您通过让两个线程同时使用连接来错误地使用它。线程问题最令人烦恼的部分是它们不会立即且始终显示 - 仅当无效使用导致诸如破坏字段的内部状态、将错误交错的数据发送到应成帧的套接字或读取等问题时数据返回不正确。基本上你在做什么是错误的。您必须立即停止使用来自多个线程的连接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    相关资源
    最近更新 更多