2014-12-04 4 views
1

이것은 Lock 객체에 대한 Oracle의 Java 자습서에있는 예제입니다. 누군가 제가 코드를 올바르게 해석했는지 확인해주십시오.스레드가 잠금을 해제 한 후에도 스레드가 계속 실행되는 이유는 무엇입니까?

다른 스레드가 같은 방식으로 작동하기 때문에 첫 번째 스레드 만 고려할 것입니다.

먼저 alphonse 잠금을 획득하고 impendingBow 메소드에 액세스합니다. 이제이 메소드는 두 인스턴스의 두 개의 잠금을 스레드에 할당하려고 시도합니다. 스레드가 두 잠금을 모두 획득 할 수 없으면 획득 한 잠금을 해제합니다. 이것은 내가 갇혀있을 때입니다. 스레드가 잠금을 해제하면 다른 인스턴스는 두 인스턴스에 모두 액세스 할 수 있으며 첫 번째 스레드는 잠금을 해제 한 직후 실행을 중지해야합니다. 하지만 실제로는 그렇지 않습니다. 여전히 부울 값을 반환하고 bow 메서드에서 else 문을 계속 실행합니다. 왜 그런 일이 일어날까요? 동기화 된 코드처럼 스레드가 잠금을 다시 얻을 때까지 스레드가 실행을 멈춰야한다고 생각했습니다.

import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 
import java.util.Random; 

public class Safelock { 
    static class Friend { 
     private final String name; 
     private final Lock lock = new ReentrantLock(); 

     public Friend(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return this.name; 
     } 

     public boolean impendingBow(Friend bower) { 
      Boolean myLock = false; 
      Boolean yourLock = false; 
      try { 
       myLock = lock.tryLock(); 
       yourLock = bower.lock.tryLock(); 
      } finally { 
       if (! (myLock && yourLock)) { 
        if (myLock) { 
         lock.unlock(); 
        } 
        if (yourLock) { 
         bower.lock.unlock(); 
        } 
       } 
      } 
      return myLock && yourLock; 
     } 

     public void bow(Friend bower) { 
      if (impendingBow(bower)) { 
       try { 
        System.out.format("%s: %s has" 
         + " bowed to me!%n", 
         this.name, bower.getName()); 
        bower.bowBack(this); 
       } finally { 
        lock.unlock(); 
        bower.lock.unlock(); 
       } 
      } else { 
       System.out.format("%s: %s started" 
        + " to bow to me, but saw that" 
        + " I was already bowing to" 
        + " him.%n", 
        this.name, bower.getName()); 
      } 
     } 

     public void bowBack(Friend bower) { 
      System.out.format("%s: %s has" + 
       " bowed back to me!%n", 
       this.name, bower.getName()); 
     } 
    } 

    static class BowLoop implements Runnable { 
     private Friend bower; 
     private Friend bowee; 

     public BowLoop(Friend bower, Friend bowee) { 
      this.bower = bower; 
      this.bowee = bowee; 
     } 

     public void run() { 
      Random random = new Random(); 
      for (int n = 0; n <5;n++) { 
       try { 
        Thread.sleep(Math.round(Math.random()*1000)); 
       } catch (InterruptedException e) {} 
       bowee.bow(bower); 
      } 
     } 
    } 


    public static void main(String[] args) { 
     final Friend alphonse = 
      new Friend("Alphonse"); 
     final Friend gaston = 
      new Friend("Gaston"); 
     new Thread(new BowLoop(alphonse, gaston)).start(); 
     new Thread(new BowLoop(gaston, alphonse)).start(); 
    } 
} 
+0

스레드가'Lock' 객체를 해제 한 후 실행을 멈추어야한다고 생각합니까? –

+0

lock 객체를 synchronized 코드와 관련시킵니다.이 코드는 잠금을 획득하면 스레드가 코드를 실행하도록하고, 그렇지 않으면 스레드를 차단합니다. – PMH

+0

잠금이 실행 중이 아니면 어떻게 확보 할 수 있습니까? –

답변

0

동기화 된 블록 사이에 미세한 차이가 있습니다 (Lock.lock(), Lock.tryLock()Lock.tryLock(timeout)).

tryLock 메서드는 호출시 다른 스레드가 보유하지 않은 경우에만 잠금을 가져옵니다. 그래서 자물쇠를 얻을 수 없을 때 즉시 반환합니다.

lock 메서드는 스레드가 대기 상태 일 때까지 잠금을 사용할 수있을 때까지 대기합니다. synchronized 문과 코드를 동기화하는 경우에도 마찬가지입니다. 스레드는 해당 코드 블록에서 잠금을 얻을 수있을 때까지 대기합니다.

tryLock(timeout) 메서드는 잠금을 사용할 수 있거나 제한 시간이 만료 될 때까지 대기합니다.

더 많은 이하는 자바 독에 설명 : 당신은 당신이 lock으로 tryLock 문을 변경하고 스레드가 결국 교착 상태에 들어갈 것을 알 수 있습니다 기대하는 행동에 대한 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html

.

+0

당신은 말했다 : tryLock 메서드는 호출시 다른 스레드가 보유하지 않은 경우에만 잠금을 획득합니다. 그래서 자물쇠를 얻을 수 없을 때 즉시 반환합니다. "즉시 반환"이란 무엇을 의미합니까? 메서드가 나머지 코드를 계속 실행한다는 의미입니까? – PMH

+0

예. 맞아요. 이 메소드는 잠금이 사용 가능하게 될 때까지 기다리지 않는다는 의미에서 즉시 반환됩니다. 'myLock'과'yourLock'에 저장된 반환 값을보고 잠금을 획득했다고 말할 수 있습니다. 이 예제에서'tryLock'을'tryLock (timeout)'으로 대체 할 수 있습니다. 그런 다음 Statement에 코드를 추가하여 소요 시간을 측정하십시오. 'tryLock (timeout)'은 타임 아웃 기간만큼 오래 걸리는 반면,'tryLock'은 오래 걸리지 않는다는 것을 알 수 있습니다. – mpkorstanje

0

스레드가 잠금을 해제 할 때 실행을 멈추지 않을 것입니다. 그것은 자물쇠를 잠그려고하지만, 그것은 명시 적으로 제어를 산출 예를

  • 을 (당신이 설정된 tryLock를 사용하기 때문에 여기에 실행을 멈추지 않을 것) 할 수

    1. : 경우 실행이 중지 sleep (sleep())
    2. 스케줄러는 다른 스레드를 더 좋아한다고 결정합니다. 모든 의도와 목적으로이 이벤트가 임의의 이벤트라고 가정해야합니다.

    여기서도 이러한 일이 발생하지 않으므로 한 스레드가 3)이 발생할 때까지 계속 실행됩니다.

  • 관련 문제