[OS / Java] 스레드와 스레드 동기화

YTT.erica·2024년 5월 23일

스레드

스레드는 프로세스보다 작은 크기의 실행 단위이다.

스레드의 출현 목적

프로세스보다 작은 시행 단위 필요
프로세스의 생성 및 소멸에 따른 오버헤드 감소
빠른 컨텍스트 스위칭
프로세스 사이의 통신에 대한 어려움 해소

스레드 개념

개념 정리
개발자 - 작업을 만드는 단위
운영체제 - 실행단위, CPU를 할당하는 스케줄링 단위

스레드는 코드, 데이터, 힙, 스택에 담긴 주소공간을 가진 실체로, 운영체제에 의해 제어됨

스레드마다 TCB(Thread Control Block)구조체를 두고, 스레드 ID, 스케줄링 우선순위 등 스레드 정보를 관리하며, 생성, 소멸, 스케줄링 등 스레드를 독립된 단위로 다룸

코드

public class Sample extends Thread {
  public void run() {
    System.out.println("thread run.");
  }

  public static void main(String[] args) {
    Sample sample = new Sample();
    sample.start();  // start()로 쓰레드를 실행한다.
  }
}

Sample 스레드를 만들고, sample.start()로 스레드 실행

멀티스레딩

멀티스레딩은 여러 스레드를 동시에 실행시킴으로서, CPU나 입출력 장치 등 컴퓨터 자원의 활용률을 높이고 사용자에게 빠른 응답 제공

  • 동시성(Concurrency)
    1개의 CPU로 2개 이상의 스레드를 시간을 나누어 실행하는 것
  • 병렬성(Parallelism)
    2개 이상의 스레드가 서로 다른 CPU에서 동시에 실행되는 것

스레드 상태와 스레드 운용

스레드의 상태 변이는 다음과 같음

  • 준비 상태(Ready) - 스레드가 스케줄을 기다리는 상태
  • 실행 상태(Running) - 스레드가 현재 CPU에 의해 실행되고 있는 상태
  • 블록 상태(Blocked) - 스래드가 입출력 요청하거나 sleep( )과 같은 시스템 호출로 커널에 의해 중단된 상태
  • 종료 상태(Terminated0- - 스레드가 종요한 상태

    츨처: https://math-coding.tistory.com/173

스레드 상태 제어

  • sleep(long millieSecond)
    인자에 입력한 수의 milliSecond 동안 스레드를 멈춤
    해당 스레드의 상태는 일시정지 상태로 전환, 시간이 경과하거나 interrupt() 메서드를 호출하면 다시 실행 대시 상태로 복귀
  • interrupt()
    일시중지 상태인 스레드를 실행 대기 상태로 복귀
  • yield()
    다른 스레드에게 실행을 양보
    실행 중인 상태에서 yield() 호출되면 실행 대기 상태로 전환
  • join()
    특정 스레드가 작업하는 동안에 자신을 일시 정지 상태로 전환하는 메서드
    다른 스레드의 작업이 끝날때까지 기다림
  • wait() / notify()
    두 스레드가 교대로 작업을 처리해야 할 때 사용
    Thread1의 작업이 끝나면 notify() 호출 -> Thread2는 실행 대기 상태로 전환, Thread1은 wait() 메서드를 호출하여 자신을 정지 상태로 만듬

스레드 종류

스레드는 스케줄링 주체에 따라 2종류로 구분

  • 커널 레벨 스레드: 커널에 의해 스케줄링되는 스레드
  • 사용자 레벨 스레드: 스레드 라이브러리에 의해 스케줄링되는 스레드

커널 레벨 스레드
TCB가 커널에 의해 커널 공간에 만들어지고 커널에 의해 스케줄되는 스레드
시스템 호출을 통해서만 만들어짐
즉, 커널 코드에 의해 만들어져, 커널에 의해 그 존재가 인지되고, 커널에 의해 스케줄링 되는 스레드 이다.

사용자 레벨 스레드
스레드 라이브러리에 의해, 사용자 공간에 생성되고, 관리되고, 스케줄되는 스레드


스레드 동기화

스레드 동기화 필요성

두 개 이상의 스레드가 공유 자원에 접근하여 동시에 변경하려고 할 때 예기치 않은 결과인 경쟁 상태를 초래할 수 있음

이유

  • 동시성 문제: 여러 스레드가 동시에 실행되면서 공유 자원에 접근하고, 서로의 작업을 방해하거나 덮어씌우는 경우
  • 순서 보장 실패: 스레드가 실행되는 순서가 매번 다르기 때문에 개발자가 원하는 순서대로 작업이 실행되지 않음

스레드 동기화

스레드 동기화란 다수의 스레드가 공유 데이터를 동시에 접근하는 충돌 상황에서 공유 데이터가 훼손되지 않도록 스레드의 실행을 제어하는 기법

임계 구역

임계 구역이란 사용자가 작성한 프로그램 중 공유 데이터에 접근하는 코드 부분
다수의 스레드로부터 공유 데이터의 훼손을 막기 위해, 임계구역은 반드시 한 스레드만 배타적 독점적으로 실행하도록 관리되어야 함
-> 이를 상호배제(Mutual Exclusion)라고 함


Mutex (상호배제)

상호배제는 멀티스레드가 실행되는 환경에서, 한 스레드가 임계구역 전체를 배타적으로 실행하도록 보장하는 기법

상호배제 위치

공유 데이터를 다루는 멀티스레드 프로그램에서 임계구역 전후에 상호배제 코드가 작성됨
임계구역 전에는 entry 코드(임계구역 진입코드), 임계구역 후에는 exit 코드(임계구역 진출코드)가 있음

상호배제 구현

임계구역에 대한 상호배제는 임계구역에 오직 한 태스크만 들어가게 하는 방책

구현 방법

  • 소프트웨어적 방법
    mutex, semaphore
  • 하드웨어적 방법
    인터럽트 서비스 금지, 원자명령 활용(spinlock, tsl, compare&swap)

멀티스레드 동기화 기법

뮤택스는 잠김/열림 중 한 상태를 가지는 락 변수를 이용하여, 한 태스크만 임계구역에 진입시키고 다른 스레드들을 큐에 대기시키는 기법

  • 메서드 동기화 스타일

    public synchronized void increment() {
       count++;
    }
  • 블록 동기화 스타일

    public void increment() {
      synchronized (lock) {
        count++;
      }
    }

주의사항

동기화된 코드 블록이 서로 다른 자원을 대기하며 교착 상태에 빠지지 않도록 주의해야 함


Semaphore (세마포어)

세마포어는 n개의 자원을 다수의 스레드가 공유하여 사용하도록 돕는 자원 관리 기법

세마포어 종류

이진 세마포어: 자원이 1개인 경우

  • 공유 자원이 1개일 때, 한 스레드가 사용중이라면, 다른 스레드는 사용이 끝날 때까지 대기

카운터 세마포어: 자원이 여러 개인 경우

  • 공유 자원이 n개일 때, n개의 공유자원이 다 사용중이라면 한개라도 사용이 끝날 때까지 대기

→ 레이스 컨디션을 방지


해당 내용은 명품 운영체제 책을 참고하여 작성한 내용입니다.

profile
'◡'✿ 꿈을 찾아가보자고~ '◡'✿

0개의 댓글