2

同時アクセスを探すたびに、私はさまざまな答えを受け取ります.JCIPの本はすでに注文していて、進行中ですが、この同時実行の基本を釘付けにしたいのですが、これが私のシナリオです.

私は3つのスレッドを持っています。1 つのスレッドは接続を確立し、シングルトン接続オブジェクト インスタンスを作成します。他の 2 つのスレッドは絶え間なくデータを送信します。

CountDownLatchこれで、接続が確立されると、接続スレッドによってゼロまでカウントダウンされるa を他のスレッドが待機します。

変数が同期され、すべてのスレッドに表示さConnectStatusれることを期待して、クラスで宣言したものを次に示します。connected

public class ConnectStatus {

public static final CountDownLatch connectionLatch = new CountDownLatch(1);
private static volatile AtomicBoolean connected;

}

接続ステータスを維持するために、揮発性でアトミックなこのconnected変数を使用しています。そのため、他のスレッドは、データを送信する前に接続が有効かどうかを「常に」知ることができます。

接続を確立したら、このブール値を true にし、ラッチをゼロにします。

ConnectStatus.connected.set(true);
ConnectStatus.connectionLatch.countdown();

これで、他のスレッドはラッチによって通知され、原子値も true になり、スレッドはデータの送信を開始します。

以下のデータ スレッド スニペットを送信します。

if(ConnectStatus.connected.get()){

   // send data

}

ここに私の問題があります。接続はいつでも悪くなり、切断される可能性があるため、その時点で、アトミックconnectedを false にしています。私が知りたいのは、このスレッドは安全ですか、他のスレッドは常にこのアトミックで揮発性の変数の更新された値を取得しますか? 接続が切断されるたびにデータの送信を停止するには、他の 2 つのスレッドが必要です。

if(ConnectStatus.connected.get()){

   // send data

}

上記のスニペットは常に正しく機能しますか?

4

2 に答える 2

3

接続はいつでも悪くなり、切断される可能性があるため、その時点で、アトミック接続を false にしています。私が知りたいのは、このスレッドは安全ですか、他のスレッドは常にこのアトミックで揮発性の変数の更新された値を取得しますか?

はいといいえ。まず、あなたAtomicBooleanはすべきであり、すべきではfinalありません volatileAtomicBooleana をラップしvolatile booleanますが、別のものに変更するつもりはありませんAtomicBoolean:

private static final AtomicBoolean connected = new AtomicBoolean(false);

を使用して接続を保護するだけの問題AtomicBooleanは (@Jeff が述べたように)、接続が接続されているかどうかをテストしても、後で直接切断される可能性があることです。

if (ConnectStatus.connected.get()) {
   // disconnect happens here, before the send
   // send data
}

でこの切断を防ぐことはできませんAtomicBoolean。接続を切断しているスレッドがすべての送信が完了するまで待機するように、ロックが必要です。

private final Object lock = new Object();
...
synchronized (lock) {
   if (connected) {
      sendData();
   }
}
...
// this has to wait for the lock to be released before it can be closed
synchronized (lock) {
   if (connected) {
      disconnect();
      connected = false;
   }
}

接続がいつ切断されるかを制御できない場合は、例外を適切にキャッチして適切に処理する必要があります。

最後に、複数の送信者が必要な場合はReentrantReadWriteLock、一度に複数のリーダーを許可する「リーダー」(面白い) として送信者をロックし、1 つのライターのみを許可する「ライター」としてクロージング スレッドをロックする必要があります。一度に。

于 2013-09-19T21:12:15.863 に答える
2

volatile可視性を保証するため、connected変数が 1 つのスレッドによって更新されると、別のスレッドからも可視になります。しかし、@Gray が彼のコメントで指摘しているように、それはあなたがしていることとはまったく異なります。AtomicBooleanアトミックな比較および設定操作を行っていない場合は、使用する必要はありません。を読んだり書いたりしているだけならboolean、それはアトミックhttp://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.htmlです。しかし、まだ競合状態があります。getの状態を確認した後connected、接続が切断されたらどうしますか?

于 2013-09-19T21:06:08.437 に答える