6

別のクラスから呼び出しているいくつかの関数のリポジトリである静的クラスを作成しました。

public static class CommonStructures
{
    public struct SendMailParameters
    {
        public string To { get; set; }
        public string From { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
        public string Attachment { get; set; }
    }
}

public static class CommonFunctions
{
    private static readonly object LockObj = new object();
    public static bool SendMail(SendMailParameters sendMailParam)
    {
        lock (LockObj)
        {
            try
            {
                //send mail
                return true;
            }
            catch (Exception ex)
            {
                //some exception handling
                return false;
            }
        }
    }

    private static readonly object LockObjCommonFunction2 = new object();
    public static int CommonFunction2(int i)
    {
        lock (LockObjCommonFunction2)
        {
            int returnValue = 0;
            try
            {
                //send operation
                return returnValue;
            }
            catch (Exception ex)
            {
                //some exception handling
                return returnValue;
            }
        }
    }
}

質問 1: 2 番目のメソッド CommonFunction2 について、新しい静的ロック、つまりこの例の LockObjCommonFunction2 を使用しますか、それとも関数の先頭で定義された同じロック オブジェクト LockObj を再利用できますか。

質問 2: スレッド関連の問題につながる可能性のあるものはありますか、またはコードを改善して安全なスレッドにすることはできますか?

質問 3: 構造体の代わりに共通クラスを渡す際に問題はありますか?

よろしく、 MH

4

4 に答える 4

5

質問 1: 2 番目のメソッド CommonFunction2 について、新しい静的ロック、つまりこの例の LockObjCommonFunction2 を使用しますか、それとも関数の先頭で定義された同じロック オブジェクト LockObj を再利用できますか。

これら 2 つのメソッドを同期する場合は、同じロックを使用する必要があります。たとえば、thread1 が Method1 にアクセスし、thread2 が Method2 にアクセスしていて、両方の内部に同時にアクセスしたくない場合は、同じ lock を使用します。ただし、同時アクセスをMethod1 または 2 だけに制限したい場合は、別の locks を使用ください。

質問 2: スレッド関連の問題につながる可能性のあるものはありますか、またはコードを改善して安全なスレッドにすることはできますか?

共有リソース (静的変数、ファイルなど) は、すべてのスレッドから簡単にアクセスできるため、スレッドセーフではないことを常に覚えておいてください。そのため、あらゆる種類の同期 (ロック、シグナル、ミューテックスなどを介して) を適用する必要があります。

質問 3: 構造体の代わりに共通クラスを渡す際に問題はありますか?

適切な同期を適用する限り、スレッドセーフになります。構造体についてはこちらを参考にしてください。

肝心なのは、共有メモリ内のすべてのものに正しい同期を適用する必要があるということです。また、生成しているスレッドのスコープと、各メソッドが使用している変数の状態に常に注意する必要があります。それらは状態を変更しますか、それとも単に変数の内部状態に依存しますか? 静的/共有ですが、スレッドは常にオブジェクトを作成しますか? はいの場合は、スレッドセーフにする必要があります。それ以外の場合、特定の共有リソースを再利用するだけの場合は、適切な同期を適用する必要があります。そして何よりも、共有リソースがなくてもデッドロックが発生する可能性があるため、C# の基本的なルールを覚えてデッドロックを回避してくださいPS Eric Lippert の記事を共有してくれた Euphoric に感謝します。

ただし、同期には注意してください。可能な限り、共有リソースが変更されている場所のみにスコープを制限します。アプリケーションに不便なボトルネックが発生し、パフォーマンスが大きく影響を受ける可能性があるためです。

    static readonly object _lock = new object();
    static SomeClass sc = new SomeClass();
    static void workerMethod()
    {
        //assuming this method is called by multiple threads

        longProcessingMethod();

        modifySharedResource(sc);
    }

    static void modifySharedResource(SomeClass sc)
    {
        //do something
        lock (_lock)
        {
            //where sc is modified
        }
    }

    static void longProcessingMethod()
    {
        //a long process
    }
于 2013-06-07T06:03:23.167 に答える
0

1)最初は、何を持ちたいかによって異なります。

そのまま (2 つの個別のロック オブジェクト) - 2 つのスレッドが同じメソッドを同時に実行することはありませんが、異なるメソッドを同時に実行することはできます。

単一のロック オブジェクトを持つように変更すると、2 つのスレッドが共有ロック オブジェクトの下でこれらのセクションを実行することはありません。

2)あなたのスニペットには、私が間違っていると思うものは何もありませんが、コードはあまりありません。リポジトリがそれ自体からメソッドを呼び出す場合、問題が発生する可能性があり、遭遇する可能性のある問題の世界があります:)

3)構造体に関しては、私はそれらを使用しません。クラスを使用すると、それらの問題を必要としない構造体に関連する問題の別の袋がある方が良い/簡単です。

于 2013-06-07T05:26:09.093 に答える
0

使用するロック オブジェクトの数は、保護しようとしているデータの種類によって異なります。複数のスレッドで読み取り/更新される変数がいくつかある場合は、独立した変数ごとに個別のロック オブジェクトを使用する必要があります。そのため、6 つの独立した変数グループを形成する 10 個の変数がある場合 (読み取り/書き込み方法に関する限り)、最高のパフォーマンスを得るには 6 つのロック オブジェクトを使用する必要があります。(独立変数とは、他の変数の値に影響を与えずに複数のスレッドで読み取り/書き込みを行う変数です。特定のアクションのために 2 つの変数を一緒に読み取る必要がある場合、それらは互いに依存しているため、一緒にロックする必要があります。これがあまり混乱しないことを願っています。)

ロックされた領域は、最大のパフォーマンスを得るためにできるだけ短くする必要があります。コードの領域をロックするたびに、ロックが解除されるまで他のスレッドはその領域に入ることができません。多数の独立変数があり、使用するロック オブジェクトが少なすぎる場合、ロックされた領域が長くなるため、パフォーマンスが低下します。

各スレッドは異なる独立した変数を読み書きできるため、より多くのロック オブジェクトを使用すると、より高い並列処理が可能になります。同じロック オブジェクト)。

コードでは、入力パラメーターに注意する必要があります。SendMailParametersこれが参照型 (構造体ではなくクラス) である場合は、そのプロパティがロックされているか、複数のスレッドでアクセスされていないことを確認する必要があります。参照型の場合、それは単なるポインターであり、プロパティのゲッター/セッター内でロックしないと、複数のスレッドが同じインスタンスのいくつかのプロパティを読み書きしようとする可能性があります。これが発生した場合、SendMail()関数は破損したインスタンスを使用することになる可能性があります。内部に単にロックを設定するだけでは十分ではありません。SendMail()プロパティとメソッドSendMailParametersも同様に保護する必要があります。

于 2013-06-07T05:27:43.737 に答える