[운영체제] 스레드(Thread)와 실무에서 마주친 관련 이슈

Posted by 유진 Blog on October 9, 2023

프로세스

사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행중 인 것.
프로그램에 사용되는 데이터, 메모리 등의 자원, 스레드로 구성됨.
프로세스는 독립된 객체로서 생성되면 각각의 메모리 자원을 할당받고 서로에게 접근이 불가능함.
프로세스간의 상태 자원을 공유하려면 IPC라는 커뮤니케이션 기법이 필요함.
IPC는 커널의 공유 메모리를 활용하여 프로세스들간의 데이서 상태 정보를 주고 받음.

스레드

프로세스 내에서 실제로 작업이 실행되는 작은 작업 단위.
모든 프로세스에는 한 개 이상의 스레드가 존재함.
둘 이상의 스레드를 동시에 실행하는 방식을 멀티 스레드라고 함.

스레드의 특징

  • 스레드는 각자 자신의 Stack 영역을 보유함.
    • 프로세스가 가지는 Stack 메모리 영역과는 별개이며, 스레드의 메모리 영역을 thread stack이라 함.
    • 프로세스는 메모리 영역을 4가지(code, data, stack, heap)으로 나눌 수 있지만, 스레드는 thead stack 메모리 공간만.
    • 스레드 안에 포함된 데이터(지역 변수)는 thread stack에 저장됨.
  • 스레드는 프로세스 내에서 Code, Data, Heap 영역을 공유함.
  • 프로세스 내부에 존재하기 때문에 프로세스의 데이터 영역에 접근이 가능함.(IPC 필요 X)

스레드의 장점

  • 성능 향상
    스레드 간의 작업 분할과 병렬 처리로 인해 빠른 응답성(결과) 제공.
  • 자원 공유 효율성 향상
    스레드는 하나의 프로세스 내에서 실행되므로 프로세스의 자원을 공유하여 접근 가능. 프로세스 내부에 있기 때문에 별도의 메모리 공간을 할당할 필요없이 프로세스 내부에서 데이터 관리하면 됨. 스레드는 프로세스 내부에서 thread stack이라는 공간에 데이터를 관리함.
  • 동시성
    여러개의 스레드를 병렬로 동시에 실행 가능.
  • 간결성
    작업을 분리할 수 있어서 코드가 간결해질 수 있음.

스레드의 단점

  • 스레드 간의 상호간섭
    멀티스레드 실행 중에 스레드 간의 상호간섭 문제 발생 가능. 스레드 간의 우선순위 설정에 문제가 있을 경우, 서로 영향을 미치기 때문에 이슈 발생 가능.
  • 성능 저하
    :스레드를 많이 생성하면 성능 저하 발생 가능. 스레드가 많이 생성되면 스레드 스케줄러에서 각각의 스레드들이 병렬로 실행되기 뒤해 context switching이 빈번하게 발생해야하기 때문에 성능 저하가 발생할 수 있음.
  • 동기화 이슈
    여러 스레드가 공유 자원에 동시에 접근할 때 동기화 문제 발생 가능. 스레드 간의 실행 순서나 타이밍에 따라 예측할 수 없는 결과 발생 가능.(race condition)
  • 자원 소비
    스레드마다 stack 및 레지스터 등의 메모리 자원을 소비하므로 스레드 수가 증가할수록 메모리 사용량도 증가하기 때문에 시스템 자원이 한계에 도달할 수 있음.

프로세스와 스레드의 차이

프로세스는 별도의 메모리 공간에서 실행되고 동일한 프로세스 내의 스레드는 공유 메모리 공간에서 실행된다는 차이점이 있다.
각 프로세스는 Code, Data, Heap, Stack 영역을 각자 보유하지만 스레드는 Code, Data, Heap만 공유하고 Stack영역은 각자 보유한다.

멀티 스레드와 멀티 프로세스

멀티 스레드 : 하나의 프로세스 내부에서 여러 개의 스레드가 동시에 실행되는 것.
스레드들끼리 서로의 메모리 공간(thread stack)을 공유하고 접근할 수 있음.
IPC 통신이 아닌 메모리 기반 통신을 사용하기때문에 통신 속도가 빠름.
각 스레드들은 자원을 공유하기때문에 하나의 스레드게 문제가 생기면 나머지 스레드는 물론 프로세스에도 영향을 미칠 수 있음.

멀티 프로세스 : 여러 프로세스가 동시에 실행되는 것.
각 프로세스는 독립된 메모리 공간을 가지며, 서로 접근하려면 IPC기법을 사용해햐 함.
각 프로세스는 각각 고유한 자원을 관리하고 있기때문에 서로 영향을 미치지 않음.

맞닥뜨렸던 관련 이슈에 관하여

상황

회사에서 RDBMS를 사용하였던 application을 SQLite로 아키텍쳐를 변경하게 됨.

문제

서비스를 이용하지 못할 정도로 빈번하게 DB Locking 이슈가 발생함.

원인

2개 이상의 서버에서 해당 application으로 초당 insert를 요청하고, application에서는 초단위와 분단위로 집계후 write하는 스케줄이 실행되고 있음. 이와 같이 멀티스레드로 빈번하게 write를 요청하는 상황에서 SQLite(File DB)특성상 write에 대해서는 싱글 스레드로 실행되기 때문에 Locking 이슈가 발생함. (File이 업데이트 되는 것이기 때문에 write는 동시에 처리될 수 없음.)

시도

write를 짧은 주기로 요청하는 함수에 대하여 retry 구문 추가
트랜잭션 isolation level 낮추기
Hikari CP 설정 바꾸기 (이전 포스팅 참고)

결과

여러 방법을 시도해보았으나 근본적인 원인(빈번한 write 요청)이 해결되지 않아서 DB Locking 이슈를 해결하는데 한계가 있었음. 결국 다른 DB를 사용하는 것으로 수정되었음.

개인 의견

해당 이슈를 해결하지 못하고 결국 또다시 아키텍처가 변경되어 한편으로는 아쉬움이 있다.
DB Locking 이슈를 해결하기 위해 여러가지 찾아보고 시도해보았을때 느꼈던 점은 이렇다.
여러 대안들이 존재하긴 하지만 SQLite의 File DB 특성상 근본적인 원인을 해결하기 어렵다고 생각한다.
그래서 대부분은 부분적으로만 SQLite를 사용하거나 임베디드로 사용하고 있는 것으로 보였는데,
현재 회사에서 다루고 있는 프로젝트와 같이 어느정도 규모가 있고 write를 빈번하게 처리해야하는 경우라면 SQLite는 이슈 해결 여부를 떠나서 이러한 아키텍처에는 적합하지 않다고 생각했다.

참고 :
https://code-lab1.tistory.com/43
https://jerryjerryjerry.tistory.com/184