1

私は現在、マルチスレッドプロジェクトに取り組んでいます。主に学習用です。このプロジェクトでの私の役割は、サーバー アプリケーションを作成することです。
しかし、この変数のロック全体が少し混乱するところまで来ました。なぜなら、それがどのように機能し、いつ/どこで使用する必要があるのか​​ 正確にはわからないからです。

class ClientHandlerを含むがあるとしましょうList<Client> clientList。を返す
ClientHandlerプロパティがあります:ClientListclientList

private List<Client> clientList;
public List<Client> ClientList
{
    get { lock (lockObject) return clientList; }
    set { lock (lockObject) clientList = value; }
}

NetworkHandlerThreadthis で動作する秒を実行しますList<>
このネットワークThreadでは、取得したものは使用中にList<>別のものにロックさobjectれます。
私の質問は、このロックがどのように機能するかです。これがネットワーク内にある
場合( とは異なる場合)、スレッドセーフですか? したがって、一般に、変数が whatである場合、他のすべての人がアクセスしようとしているためにロックされているというのは本当ですか? 別の で処理されている間は を変更できないこと を確認したいだけです。lockList<>ThreadobjectClientHandlerlockobject
List<>Thread

4

1 に答える 1

3

オブジェクト自体ではなく、 Add/Remove/Clear/foreach メソッドを介して別のスレッドで List 自体を渡して操作することを想定しています。

この場合、リスト自体が各操作 (追加、削除など) で内部ロック メカニズムを実装する必要があります。あなたではなく、リストが を作成しlockObjectます。

明らかにList<T>これを行うことはできないため、それから派生させるか、独自の IList/ICollection クラスを実装する必要があります。または、System.Collections.Concurrentこの目的のために既に設計されている名前空間のコレクションを使用することもできますConcurrentDictionary

コレクション内のオブジェクトに複数のスレッドからアクセスできるようにしたい場合は、それらのオブジェクトをスレッドセーフにする必要があります...これは完全に別の手順です。

lock キーワードの仕組みの簡単な説明:

を指定してオブジェクトをロックするlock (someObject) { }と、コード ブロック内のすべてが、同じオブジェクトのロックの他のすべてのインスタンスが実行されていない場合にのみ実行されます。

ロック コード ブロックの開始時に、「このオブジェクトを予約しています」というスレッド セーフ フラグをどこかに設定し、ロック ブロックの最後で、「このオブジェクトはもう予約していません」と伝えます。ロック ブロックの開始時にオブジェクトをロックしようとしたが、そのオブジェクトが既にロックされている場合は、ロックを正常に取得できるまで無期限に待機し、プロセス内の呼び出しスレッドをブロックします。

あなたの例では、インライン コード ブロックを使用しています。

get { lock (lockObject) return clientList; }

これは次と同等です:

get
{
    lock (lockObject)
    {                       // Lock starts here
        return clientList;
    }                       // Lock ends here
}

したがって、そのプロパティにアクセスすると、プロパティの呼び出し元に渡されるとすぐにオブジェクトのロックが解除されます。その後、呼び出し元は先に進み、その List で Add() メソッドを呼び出すことができます。内部的には、ロック メカニズムなしで内部コレクションにアクセスするため、スレッド セーフではありません。

_innerList代わりに、次のように、フィールドなどの内部フィールドにアクセスするたびに、List で lock を呼び出す必要があります。

public void Add(object item)
{
    lock (_innerList)
    {
        _innerList.Add(item);
    }
}
于 2013-09-30T19:17:48.820 に答える