文字列をロックオブジェクトとして使用しても問題ありませんか? 質問する

文字列をロックオブジェクトとして使用しても問題ありませんか? 質問する

文字列の有限集合に基づいて、ある領域にクリティカルセクションを作成する必要があります。同じ文字列インスタンスに対してロックを共有したいのですが、(文字列.インターンアプローチ)。

以下の実装を検討しています。

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 を作成する方がよいでしょうか。

はい。安全のためだけに。大規模システムでは、デッドロックを回避する主な目的は、ロック オブジェクトを可能な限りローカルかつプライベートに保つことです。限られた量のコードだけがロック オブジェクトにアクセスできるようにする必要があります。

おすすめ記事