본문 바로가기
Computer Science/운영체제

스레드 안전(Thread Safe)을 지키기 위한 방법

by Libi 2021. 8. 15.
반응형

스레드란 CPU 이용의 기본 단위로써 프로세스의 실행 단위이다.

하나의 프로세스는 한 개 이상의 스레드를 가질 수 있는데, 이처럼 다수의 스레드를 수행하는 것을 멀티 스레딩이라고 한다.

프로세스 내부의 스레드들은 각각 스택 영역을 독립적으로 가지지만 스택 영역을 제외한 힙, 데이터 영역을 서로 공유하기 때문에 스레드들이 동시에 공유 자원에 접근하게 되면 예상치 못한 결과가 발생할 가능성이 생기게 된다.

 

간단한 예시로 현재 통장에 100만원이 들어있다고 하자.

만약 공유 자원에 대한 동시 접근을 막지 않았다면 N명이 동시에 100만원을 출금을 해버리면 100만원이 Nx100만원이 돼버리는 문제가 발생하게 된다.

이러한 상황을 "스레드 안전(Thread Safe)하지 않은 상황"이라고 부른다.

 

스레드 안전(Thread Safe)이란 멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없음을 의미한다.

보다 엄밀하게는 하나의 함수가 한 스레드로부터 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하여 동시에 함께 실행되더라도 각 스레드에서의 함수의 수행 결과가 올바르게 나오는 것으로 정의한다.

 

우리는 이와 같은 문제가 발생하지 않도록 하기 위해서 Thread Safe를 보장해줘야 한다. 이를 보장해주는 방법에 대해 알아보자.

 

 

Re-entrancy

  • 어떤 함수가 한 스레드에 의해 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 올바르게 주어져야 한다.
  • 뭔가 말이 어려워 보이지만 결국 함수에서 사용되는 변수들을 각 스레드에게 독립적인(다른 스레드에게 영향을 주지 않음) 변수를 사용하도록 설계하라는 의미인 것 같다.

 

Thread-local storage

  • 공유 자원의 사용을 최대한 줄여 각각의 스레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는다.
  • 즉, 스레드끼리 공유하는 힙, 데이터 영역의 자원 접근을 최소화하고, 각 스레드가 독립적으로 가지는 스택 영역의 자원만 사용하도록 설계하라는 의미인 것 같다.

 

Immutable objects

  • 공유 자원을 사용한다면 불변 객체를 사용하라는 의미이다. 불변 객체는 변하지 않는 읽기 전용 자원이기 때문에 여러 스레드가 동시에 접근해도 스레드 안전성이 보장된다.
  • Java에서 대표적인 immutable 객체로 String 객체가 존재한다.
  • 만약 변경 가능한 객체를 사용한다면 공유 객체를 그대로 가져와서 사용하지 말고 새로운 객체를 생성하여 공유 자원 객체의 값들을 복사하여 사용하자.
  • 약간 DB에서 Entity를 그대로 들고 와서 사용하지 말고 DTO를 통해 사용하는 것과 비슷한 의미인 것 같다.

 

Mutual exclusion

  • 공유 자원을 꼭 사용해야 할 경우 해당 자원의 접근을 세마포어 등의 락으로 통제한다.
  • Java의 synchronized를 사용하라는 의미이다.
  • synchronized 키워드를 사용하면 어떤 한순간에는 하나의 스레드 만이 임계 영역(Critical Section) 안에서 실행하는 것이 보장된다.

 

Atomic operations

  • 공유 자원에 접근할 때 원자 연산을 이용하거나 '원자적'으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현할 수 있다.
  • 원자적 연산이란 중단되지 않는 연산을 의미하며 스레드가 절대 간섭할 수 없음이 보장된다.

 

 

 

[ Reference ]

· https://en.wikipedia.org/wiki/Thread_safety

 

반응형

댓글