我不喜欢锁定了我的代码 同步(这个), 所以我在尝试利用 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 );
        }
    }
}
  1. 根据我的代码,是吗线的安全要点,如果2线试图呼叫 connect() 同时,只有一个连接的企图是不允许的。

  2. 在最后块,我在执行两个AtomicBoolean.设置(..),在继承,将会有一个问题,因为在之间的差距,这2个原子的电话,一些螺纹可以叫 _connected.获得() 在其它的方法吗?

  3. 当使用 _xmppConn, 我应该做一个 同步(_xmppConn) ?

更新 加入失踪登录到的方法。

有帮助吗?

解决方案

  1. 是的。可变_connecting作为一个试验和设置的锁,阻止多个同时连接的企图。

  2. 没有问题-即使另一个螺纹读取_connected之间写道,_connecting会防止它试图连接同时进行。

  3. 是的,假定其方法是不是已经线的安全。

这就是说,您的连接()方法将推动我坚果在其目前的形式,因为它不一定连接或投掷的一个例外。你可以添加一个旋循环,但这不是一个真正的好,合适,因为所有,但最短的网络跳从多处理机,它将更有效率。低级别的并发原语,而且,更多的错误易于同步的-我 强烈 建议你坚持同步。

其他提示

请记住,使用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.
  }
}

如果你正在做的并行程中爪哇,我强烈推荐读 Java并发在实践.

我想其他人都复盖的正确性的充分在他们的意见。我仅仅另外的评论是,我感到关切的是一些关于安置的放在最后。好像你可能会真正想要的包裹全框有(包括_xmppConnProvider.获得()call)在尝试{}最后{}这将保证你会永远释放锁。否则,某种未经检查的例外可能发生在那里并且离开你一个不可恢复的状态。

在文体上,我认为,这代码作为更加难以理解不是简单地使用同步/锁,以实现相互排斥。我会启动代码,是易于理解并且仅使它更加复杂,如果你能证明,这是一个热点。

我怀疑你的程序将线的安全。我没有Java存储器模型的大师,但从我所了解到的操作,可安排和结果的行动可能看不到其他的螺纹在了您的期望。

考虑,如果例如设置 _connected 到真实之前执行的连接()方法是充分执行?另外一个线程可能认为你是连接的,即使你不是。这只是猜测-我不知道,特定问题可发生在所有。

我是说,排序锁定你们试图要做的是非常棘手的得到的权利。坚持同步,或者使用锁在 java。工具.并行。锁 包。

  1. 它是绝对满意。作为_connecting.compareAndSet(false,true)将允许只有一个线程,以获得。

  2. 你不需要设置_connected.设置(false);作为这是永远不会设置为真实的,如果异常的事情发生了。是的它可能不是由于继承,但直到您没有设置连接到假其他线试图连接不会做想,一个连接正在进行中。

  3. 是的如果xmppConn是无线的安全。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top