Synchronized(this)でコードをロックするのは好きではないので、 AtomicBooleansを使って実験しています。コード スニペットでは、XMPPConnectionIF.connect()がリモート サーバーへのソケット接続を作成します。変数_connectingはconnect()メソッドでのみ使用されることに注意してください。_connectedは、 _xmppConnを使用する必要がある他のすべてのメソッドで使用されます。私の質問は、以下のコード スニペットの後にリストされています。
private final AtomicBoolean _connecting = new AtomicBoolean( false );
private final AtomicBoolean _connected = new AtomicBoolean( false );
private final AtomicBoolean _shuttingDown = new AtomicBoolean( false );
private XMPPConnection _xmppConn;
/**
* @throws XMPPFault if failed to connect
*/
public void connect()
{
// 1) you can only connect once
if( _connected.get() )
return;
// 2) if we're in the middle of completing a connection,
// you're out of luck
if( _connecting.compareAndSet( false, true ) )
{
XMPPConnectionIF aXmppConnection = _xmppConnProvider.get();
boolean encounteredFault = false;
try
{
aXmppConnection.connect(); // may throw XMPPException
aXmppConnection.login( "user", "password" ); // may throw XMPPException
_connected.compareAndSet( false, true );
_xmppConn = aXmppConnection;
}
catch( XMPPException xmppe )
{
encounteredFault = true;
throw new XMPPFault( "failed due to", xmppe );
}
finally
{
if( encounteredFault )
{
_connected.set( false );
_connecting.set( false );
}
else
_connecting.compareAndSet( true, false );
}
}
}
私のコードに基づいて、2 つのスレッドが同時にconnect()を呼び出そうとした場合、1 つの接続試行のみが許可されるという点までスレッド セーフですか。
finally ブロックで、2 つの AtomicBoolean.set(..) を連続して実行していますが、これら 2 つのアトミック呼び出しの間のギャップの間に、一部のスレッドが他のメソッドで_connected.get()を呼び出す可能性があるため、問題はありますか?
_xmppConnを使用する場合、synchronized( _xmppConn )を実行する必要がありますか?
更新欠落していたログイン呼び出しをメソッドに追加しました。