문제

나는 내 코드를 잠그는 것을 좋아하지 않습니다 동기화 (this), 그래서 나는 사용을 실험하고 있습니다 Atomicbooleans. 코드 스 니펫에서 xmppconnectionif.connect () 원격 서버에 소켓을 연결합니다. 변수입니다 _ 연결 is only ever used in the 연결하다() 방법; 반면 _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 개의 스레드가 호출을 시도하는 시점까지 스레드가 안전합니까? 연결하다() 동시에 하나의 연결 시도 만 허용됩니다.

  2. 마지막으로 블록에서, 나는 두 개의 Atomicboolean.set (..)를 연속적으로 실행하고있다. _connected.get () 다른 방법으로?

  3. 사용할 때 _xmppconn, 내가해야할까요 동기화 (_xmppconn) ?

업데이트 누락 된 로그인 호출이 메소드에 추가되었습니다.

도움이 되었습니까?

해결책

  1. 예. 변수 _connecting은 여러 동시 연결 시도를 방지하는 테스트 및 세트 잠금으로 작용합니다.

  2. 문제 없음 - 다른 스레드가 쓰기 사이에 _connected를 읽더라도 _Connecting은 동시에 연결을 시도하지 못하게합니다.

  3. 예, 그 방법이 아직 스레드 안전하지 않다고 가정합니다.

즉, Connect () 메소드는 반드시 연결되거나 예외를 던지지 않기 때문에 현재 형태로 미치광이를 유도 할 것입니다. 스핀 루프를 추가 할 수는 있지만 멀티 프로세서 머신에서 가장 짧은 네트워크 홉을 제외한 모든 것의 경우 수율이 더 효율적이기 때문에 실제로 적합하지는 않습니다. 또한 저수준 동시성 프리미티브는 동기화 된 것보다 훨씬 더 오류가 발생합니다. 강하게 동기화 된 것을 고수하는 것이 좋습니다.

다른 팁

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.get () 호출 포함)를 실제로 랩핑하고 싶을 것 같습니다. 그렇지 않으면, 어떤 종류의 선택되지 않은 예외가 거기에서 발생하고 당신을 정찰 할 수없는 상태로 남길 수 있습니다.

스타일 적으로, 나는이 코드를 단순히 동기화/잠금을 사용하여 상호 배제를 달성하는 것보다 추론하기가 훨씬 더 어렵다고 생각합니다. 나는 추론하기 쉬운 코드로 시작하고 이것이 핫스팟임을 증명할 수 있다면 더 복잡하게 만듭니다.

나는 당신의 프로그램이 스레드 안전이 될지 의심합니다. 나는 Java 메모리 모델 전문가가 아니지만, 배운 작업에서 작업을 정리할 수 있으며 작업 결과가 기대하는 순서대로 다른 스레드에 보이지 않을 수 있습니다.

예를 들어 설정하는 경우 고려하십시오 _connected Connect () 메소드가 완전히 실행되기 전에 true가 실행됩니까? 다른 스레드는 그렇지 않더라도 연결되어 있다고 생각할 수 있습니다. 이것은 단지 추측입니다. 특정 문제가 전혀 발생할 수 있는지 확신 할 수 없습니다.

내 요점은 오히려 당신이하려고하는 잠금의 종류가 올바르게되기가 매우 까다 롭다는 것입니다. 동기화 된 상태로 고수하거나 잠금 장치를 사용하십시오 java.util.concurrent.locks 패키지.

  1. 예, 확실히 만족합니다. _connecting.compareAndset (false, true)은 하나의 스레드 만 들어가도록 허용합니다.

  2. _connected.set (false)를 설정할 필요가 없습니다. 예외가 발생하면 결코 진실로 설정되지 않으므로 절대 설정되지 않습니다. 예, 승계 때문이 아니라 연결을 시도하는 거짓 다른 스레드에 연결하지 않을 때까지 연결이 진행 중이라고 생각하지 않을 것입니다.

  3. 예 XMPPConn이 스레드 안전하지 않은 경우.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top