java 다중 스레드 - 자물쇠 상세 및 예시 코드
간단한 자물쇠 하나
자바의 동기화 블록부터 시작합니다.
public class Counter{
  private int count = 0;
  public int inc(){
    synchronized(this){
      return ++count;
    }
  }
}
다음 Counter 클래스는 synchronized 대신 Lock으로 동일한 목적을 달성합니다.
public class Counter{
  private Lock lock = new Lock();
  private int count = 0;
  public int inc(){
    lock.lock();
    int newCount = ++count;
    lock.unlock();
    return newCount;
  }
}
여기에는 Lock 클래스의 간단한 구현이 있습니다.
public class Counter{
public class Lock{
  private boolean isLocked = false;
  public synchronized void lock()
    throws InterruptedException{
    while(isLocked){
      wait();
    }
    isLocked = true;
  }
  public synchronized void unlock(){
    isLocked = false;
    notify();
  }
}
루틴이 임계구 (lock () 와 unlock () 사이에 있는 코드를 완성하면 unlock () 를 호출합니다.unlock () 을 실행하면 isLocked 를false 로 다시 설정하고, 그 중 하나 (있으면) 를 lock () 방법에서wait () 함수를 호출하여 대기 중인 라인에 알립니다.
자물쇠의 재입성
Java의 synchronized 동기화 블록은 다시 들어갈 수 있습니다.이것은 만약에 하나의 자바 라인이 코드의synchronized 동기화 블록에 들어갔고 이 동기화 블록이 사용하는 동기화 대상에 대응하는 파이프의 자물쇠를 얻었다면 이 라인은 같은 파이프 대상이 동기화하는 다른 자바 코드 블록에 들어갈 수 있음을 의미한다.다음은 예입니다.
public class Reentrant{
  public synchronized outer(){
    inner();
  }
  public synchronized inner(){
    //do something
  }
}
앞에서 제시한 자물쇠는 다시 들어갈 수 있는 것이 아니다.만약 우리가 아래와 같이 Reentrant 클래스를 다시 쓴다면, 루트가 outer () 를 호출할 때, inner () 방법의 lock에 있습니다.lock () 에서 막습니다.
public class Reentrant2{
  Lock lock = new Lock();
  public outer(){
    lock.lock();
    inner();
    lock.unlock();
  }
  public synchronized inner(){
    lock.lock();
    //do something
    lock.unlock();
  }
}
두 번 lock () 사이에 unlock () 를 호출하지 않으면 두 번째 lock () 호출이 막힙니다. lock () 가 실현되는 것을 보면 그 원인이 뚜렷합니다.
public class Lock{
  boolean isLocked = false;
  public synchronized void lock()
    throws InterruptedException{
    while(isLocked){
      wait();
    }
    isLocked = true;
  }
  ...
}
이 Lock 클래스를 재입력할 수 있도록 약간의 변경이 필요합니다.
public class Lock{
  boolean isLocked = false;
  Thread lockedBy = null;
  int lockedCount = 0;
  public synchronized void lock()
    throws InterruptedException{
    Thread callingThread =
      Thread.currentThread();
    while(isLocked && lockedBy != callingThread){
      wait();
    }
    isLocked = true;
    lockedCount++;
    lockedBy = callingThread;
 }
  public synchronized void unlock(){
    if(Thread.curentThread() ==
      this.lockedBy){
      lockedCount--;
      if(lockedCount == 0){
        isLocked = false;
        notify();
      }
    }
  }
  ...
}
그 밖에 우리는 같은 라인에서 자물쇠 대상에 대한 자물쇠를 반복하는 횟수를 기록해야 한다.그렇지 않으면, 현재 자물쇠가 여러 번 잠겼더라도 unblock () 호출을 한 번 하면 전체 자물쇠가 해제됩니다.unlock () 호출이 lock () 호출에 대응하는 횟수에 도달하기 전에, 우리는 자물쇠가 해제되는 것을 원하지 않습니다.
이제 이 Lock 클래스는 다시 들어갈 수 있습니다.
자물쇠의 공평성
Java의synchronized 블록은 그들의 라인에 들어가려는 순서를 보장하지 않습니다.따라서 만약에 여러 개의 라인이 같은 synchronized 동기화 블록을 계속 경쟁적으로 방문한다면 위험이 존재한다. 그 중 하나 또는 여러 개의 라인은 영원히 방문권을 얻지 못한다. 즉, 방문권은 항상 다른 라인에 분배된다는 것이다.이런 상황을 라인 기아라고 부른다.이런 문제를 피하기 위해서는 자물쇠가 공평성을 실현해야 한다.본고에서 보여준 자물쇠는 내부에synchronized 동기화 블록으로 이루어져 있기 때문에 공평성을 보장하지 않는다.
finally 문장에서 unlock () 을 호출합니다
만약 Lock으로 임계 구역을 보호하고 임계 구역에 이상이 발생할 수 있다면,finally 문장에서 unlock () 를 호출하는 것이 매우 중요하다.이렇게 하면 이 자물쇠 대상이 다른 라인이 계속 자물쇠를 채울 수 있도록 해제될 수 있음을 보장할 수 있다.다음은 예입니다.
lock.lock();
try{
  //do critical section code,
  //which may throw exception
} finally {
  lock.unlock();
}
이상은 자바 다중 스레드 자물쇠에 대한 자료 정리입니다. 후속적으로 관련 자료를 계속 보충합니다. 본 사이트에 대한 지지에 감사드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.