Contents

스레드

Contents

출처: [병렬프로그래밍] 자바 병렬 프로그래밍 소개

스레드 사용

  1. 안전성 위해 요소

    UnsafeSequence는 비표준 어노테이션인 @NotThreadSafe를 사용.(@ThreadSafe와 @Immutable도 존재)

    • @Immutable은 해당 클래스가 불변 클래스임을 나타내기 때문에 ThreadSafe

    만약 @ThreadSafe라고 표시하면 클래스를 사용하는 사람은 멀티스레드 환경에서 문제가 없다는 점을 명확히 알 수 있고, 스레드 안전성이 계속 보장돼야 한다는 점에 주의할 수 있다.

    스레드는 같은 메모리 주소 공간을 공유하고 동시에 실행되기 때문에 다른 스레드가 사용 중일지도 모르는 변수를 읽거나 수정할 수도 있다.

    다른 스레드간 통식방식보다 데이터 공유가 훨씬 쉬운 이점이 있지만, 경쟁 조건(race condition)의 위험성이 있다.

    멀티스레드 프로그램이 동작하는 모습을 생각하려면 스레드들이 서로 간섭하지 않도록 공유 변수에 접근하는 부분에 대해 적절하게 조율해야 한다.

    다행히 자바에서는 공유 변수 접근을 조율하기 위한 동기화 수단이 제공되고 있다. UnsafeSequenc를 바로 잡으려는 방법 가운데 하나를 보자 getNext를 동기화된 메소드로 만들면 문제가 해결된다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    @ThreadSafe
    public class Sequence {
      @GuardedBy("this") private int value;
      // @GuardedBy(lock) 어노테이션은 해당 필드나 메소드를 사용하려면 반드시 지정된 락을 확보한 상태에서 사용해야 한다는 점을 의미 (출처: https://aroundck.tistory.com/3423)
    
      // 스레드 안전한 일련번호 생성
      public synchronized int getNext() {
        return value;
      }
    }
    

    동기화를 하지 않으면 실행 시점이나 순서를 자유롭게 조정할 수 있다. 레지스터나 캐시 메모리에 변수를 캐시해둘 수도 있다.(다른 스레드에 보이지 X)

    이런 요령은 성능을 향상하는 데 도움이 되고 바람직하기도 하지만, 최적화 작업 때문에 프로그램에 오류가 발생하지 않도록 스레드 간에 데이터가 공유되고 있는지를 명확하게 구분해줘야 하는 부담이 있다.

  2. 활동성 위험 스레드를 사용할 때에는 단일 스레드에서는 나타나지 않는 활동성 장애 위험이 있다. 활동성 = 원하는 일이 결국 일어난다 작업이 전혀 진전되지 못하는 상태일 때 활동성 장애. -> 데드락, 기아상태, 라이브락 등 여러 가지 활동성 장애가 존재

  3. 성능 위험 스레드를 사용하면 부하가 생길 수 O. 스레드가 많을 경우 context switching이 빈번하고 부담이 생김 메모리를 읽고 쓰는 데에 있어 지역성 손실. CPU 시간을 스케줄링에 소모하는 부분 필요. 또한, 스레드가 데이터를 공유할 때에는 동기화 수단도 사용해야 됨. 이런 동기화는 컴파일러 최적화를 방해하고 메모리 캐시를 지우거나 무효화. 공유 메모리 버스에 동기화 관련 트래픽을 유발하기도 함.