Jac*_*ine 2 java concurrency multithreading xmpp smack
我不喜欢用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 );
}
}
}
Run Code Online (Sandbox Code Playgroud)
根据我的代码,如果2个线程同时尝试调用connect(),那么它是否是线程安全的,只允许一次连接尝试.
在finally块中,我连续执行两个AtomicBoolean.set(..),会出现问题,因为在这两个原子调用之间的间隙中,某些线程可能在其他方法中调用_connected.get()?
使用_xmppConn时,我应该进行同步(_xmppConn)吗?
更新在方法中添加了缺少的登录调用.
请记住,使用3 AtomicBooleans是不一样的守着这三个变量与单个锁.在我看来,这些变量的状态构成了对象的单个状态,因此它们应该被同一个锁保护.在使用原子变量的代码,有可能为不同的线程更新的状态_connected,_connecting和_shuttingDown独立-用原子变量只能保证访问相同的变量是多个线程之间的同步.
也就是说,我不认为同步this就是你想做的事情.您只想同步访问连接状态.你可以做的是创建一个对象,用作此状态的锁,而无需启用监视器this.即:
class Thing {
Boolean connected;
Boolean connecting;
Boolean shuttingDown;
Object connectionStateLock = new Object();
void connect() {
synchronized (connectionStateLock) {
// do something with the connection state.
}
}
void someOtherMethodThatLeavesConnectionStateAlone() {
// free range thing-doing, without getting a lock on anything.
}
}
Run Code Online (Sandbox Code Playgroud)
如果您正在使用Java进行并发编程,我强烈建议您阅读Java Concurrency In Practice.
是.变量_connecting充当测试和设置锁,可防止多个并发连接尝试.
没问题 - 即使另一个线程在写入之间读取_connected,_connecting也会阻止它尝试同时连接.
是的,假设它的方法不是线程安全的.
话虽这么说,你的connect()方法会以当前形式驱使我疯狂,因为它不一定连接或抛出异常.你可以添加一个旋转循环,但这并不是一个很好的选择,因为除了多处理器机器中最短的网络跳跃之外,它的产生效率会更高.此外,低级并发原语比同步更容易出错 - 我强烈建议你坚持使用synchronized.
| 归档时间: |
|
| 查看次数: |
4107 次 |
| 最近记录: |