文字列の有限集合に基づいて、ある領域にクリティカルセクションを作成する必要があります。同じ文字列インスタンスに対してロックを共有したいのですが、(文字列.インターンアプローチ)。
以下の実装を検討しています。
public class Foo
{
private readonly string _s;
private static readonly HashSet<string> _locks = new HashSet<string>();
public Foo(string s)
{
_s = s;
_locks.Add(s);
}
public void LockMethod()
{
lock(_locks.Single(l => l == _s))
{
...
}
}
}
このアプローチに何か問題はありますか? この方法で文字列オブジェクトをロックしても問題ありませんか? また、 を使用するとスレッドの安全性に問題はありますかHashSet<string>
?
たとえば、Dictionary<string, object>
文字列インスタンスごとに新しいロック オブジェクトを作成する を作成したほうがよいでしょうか。
最終的な実装
提案に基づいて、私は次の実装を採用しました。
public class Foo
{
private readonly string _s;
private static readonly ConcurrentDictionary<string, object> _locks = new ConcurrentDictionary<string, object>();
public Foo(string s)
{
_s = s;
}
public void LockMethod()
{
lock(_locks.GetOrAdd(_s, _ => new object()))
{
...
}
}
}
ベストアンサー1
文字列のロックは推奨されません。主な理由は、(文字列インターンにより) 知らないうちに他のコードが同じ文字列インスタンスをロックする可能性があるためです。デッドロック状況が発生する可能性があります。
これは、ほとんどの具体的な状況ではおそらく無理なシナリオです。これはむしろ、図書館の一般的なルールです。
しかし、一方で、文字列の利点とは何でしょうか?
つまり、ポイントごとに次のようになります。
このアプローチには何か問題がありますか?
はい、しかしほとんどは理論的なものです。
このように文字列オブジェクトをロックしても問題ありませんか? また、HashSet を使用するとスレッドの安全性に問題はありますか?
HashSet<>
スレッドが同時に読み取りを行う限り、スレッドセーフティには関係ありません。
たとえば、文字列インスタンスごとに新しいロック オブジェクトを作成する Dictionary を作成する方がよいでしょうか。
はい。安全のためだけに。大規模システムでは、デッドロックを回避する主な目的は、ロック オブジェクトを可能な限りローカルかつプライベートに保つことです。限られた量のコードだけがロック オブジェクトにアクセスできるようにする必要があります。