1

このようなコードに出くわしました。

public class ConnectionUtility
{
    private static SqlConnection con;

    public static SqlConnection GimmeConnection()
    {
        if(con==null)
            con = new SqlConnection();
        return con;
    }
}

これは ASP.NET Web アプリケーションにあります。1 つの要求/ページが接続上で実行するものをオープン/クローズしようとし、他の要求もそれらのことを実行しようとする競合状態があると予想できますか?

4

5 に答える 5

4

はい、競合状態は間違いなく可能です。複数のスレッドが同時に呼び出しGimmeConnection()、すべてが新しい接続を作成する可能性があるため、の初期化には競合状態がありますcon

.NETでこれを行う正しい方法は、実際にはかなり簡単です。

public class ConnectionUtility
{
    private static SqlConnection con = new SqlConnection();

    public static SqlConnection GimmeConnection()
    {
        return con;
    }
}

これは、競合状態がなくても機能することが保証されています。

もちろん、これによって修正されない別の競合状態も考えられます。

グローバルにアクセス可能な単一の接続を作成するため、複数のスレッドがそれを同時に使用するのは簡単ですが、これは安全ではありません。

接続が複数のスレッドで使用されている場合、これらのアクセスは、たとえばロックを介して明示的にシリアル化する必要があります。

もちろん、最善の行動は、そもそもシングルトンを回避することです...

于 2012-08-14T13:55:00.850 に答える
1

はい...複数のスレッドに沿って単一の静的接続を共有しないでください。これは競合状態の問題だけではありません。同じ接続を同時に使用しようとする多くのWebページがあり、機能しません。

「con」で[ThreadStatic]属性を使用すると、スレッドスコープでグローバルになります。

于 2012-08-14T13:54:29.463 に答える
1

はい、そのような競合状態が予想されます。良いスポッティング!

于 2012-08-14T13:55:14.470 に答える
1

2 つの競合状態、1 つは潜在的に無害で、もう 1 つは恐ろしいものです。論理エラーもあります。

潜在的に無害なものは、次のコンストラクター ロジックにあります。

if(con==null)
  con = new Thing();

単一のオブジェクトを最適化として使用したい場合、これは無害ですが、複数のオブジェクトを使用する期間を持つことは、間違っているというよりもむしろ最適ではありません (すべてのレースが世界の終わりというわけではありません)。それは、何Thingがどのように使用されるかによって異なります。

悲惨なレースは次のとおりです。

return con;

この場合、タイプはSqlConnectionであり、これはスレッドセーフではないため、プロパティを使用するたびに、災難を招く競争になります。

論理エラーは、生成するのが軽く、重い部分の独自のスレッドセーフなプーリングを処理するオブジェクトをシングルトン キャッシュに持つことにあります。このプーリングのため、SqlConnection必要以上に を保持するべきではありません。確かに、ある使用と別の使用の間にギャップがある場合 (それ自体に悪臭があります)、それを閉じて、再度開く必要があります。これにより、提供されるスレッドセーフなプーリングがSqlConnection、使用間で最も最適に機能します。

于 2012-08-14T14:29:09.537 に答える
0

シングルトンを書くときはいつでも、それらをスレッドセーフにする必要があります。

  class Singleton 
  {
    private Singleton() { }
    private static volatile Singleton instance;

    public static Singleton GetInstance() 
    {
       // DoubleLock
       if (instance == null) 
       {
          lock(m_lock) {  
             if (instance == null) 
             { 
                instance = new Singleton();
             }   
          }
       }
       return instance;
    }

    // helper
    private static object m_lock = new object();
  }
于 2012-08-14T13:56:24.520 に答える