2017-05-07 1 views
0

Hewlett Packard Enterprise 응용 프로그램 Fortify On Demand에는 "예제 2 : 다음 코드는 항상 잠금을 해제합니다."라는 제목의 코드 조각이 들어 있습니다.이 잠금 관리 코드 스 니펫이 불필요하게 복잡합니까?

ReentrantLock myLock = new ReentrantLock(); 

try { 
    myLock.lock(); 
    performOperationInCriticalSection(); 
    myLock.unlock(); 
} 
finally { 
    if (myLock != null) { 
     myLock.unlock(); 
    } 
} 

이미 finally에서 처리 될 때 잠금을 해제 할 수있는 try 블록의 마지막 행은,이 이유는 무엇입니까? 정말 필요한가, 아니면 좀 더 자세한 코딩 표준의 일부일 뿐인가? if도 필요하지 않습니다.

답변

1

코드 throws an IllegalMonitorStateException입니다. 왜냐하면 unlock()을 연속적으로 두 번 호출하기 때문입니다. ReentrantLock.unlock에서

:

예외 :

IllegalMonitorStateException - 현재의 thread가이 락

을 보유하지 않는 경우

나는 코드가 잘못되었다고 말해야 할 것이며, 나는 그들이 무엇을하려고하는지에 대해 정말로 추측 할 수 없다. try 블록 안에 unlock() 블록 바로 다음에 myLock = null; 블록이 있으면 작동 할 수 있지만 여전히 그렇게하는 것은 엉성한 코드입니다. unlock()이 예외를 throw하면 unlock()의 두 번째 호출도 다른 예외를 throw합니다.

올바른 관용구는 다음과 같은 문서에 따라 이와 같습니다. Lock : 당신이 정말 안전하려면

Lock l = ...; 
l.lock(); 
try { 
    // access the resource protected by this lock 
} finally { 
    l.unlock(); 
} 

, 당신은 시도 -과 - 자원close()이 예외가 발생하면 try 블록에서 예외가 발생하는 동안 사실을 활용하는 데 사용할 수있는, close() 예외가 억제 된 예외에 추가되므로 어느 것도 손실되지 않습니다.

class Locker implements AutoCloseable { 
    private final Lock lock; 
    Locker(Lock lock) { this.lock = Objects.requireNonNull(lock); 
         this.lock.lock(); } 
    @Override public void close() { lock.unlock(); } 
} 

Lock lock = ...; 
try (Locker locker = new Locker(lock)) { 
    // If both modifySharedState() and unlock() 
    // throw an exception, the unlock() exception 
    // is added to the modifySharedState() 
    // exception's suppressed list. 
    modifySharedState(); 
} 

(Here's an example output using that code on Ideone.)을 (unlock()는 예외가 발생하면 앞의 예와 HP 예 모두에서, 예외는 try 블록이 완전히 손실에서. 슬로우) 또는 당신은 뭔가를 쓸 수 코드 which try-with-resources translates to :

Lock lock = ...; 
lock.lock(); 
Throwable primary = null; 
try { 
    modifySharedState(); 
} catch (Throwable x) { 
    primary = x; 
    throw x; 
} finally { 
    try { 
     lock.unlock(); 
    } catch (Throwable x) { 
     if (primary != null) { 
      primary.addSuppressed(x); 
      // primary is already "in-flight" 
      // so no need to throw it again 
     } else { 
      throw x; 
     } 
    } 
} 

따라하기에 약간 어렵습니다.

논리 그냥 lock()...unlock()보다 더 복잡한 경우 하나 이상의 잠금을 가지고 또는 unlock() 어떤 이유로 조건 인 경우, 예를 들어, 감각을 만들 수있는 예외를 던지는 unlock()에 대한 회계.

관련 문제