만쥬의 개발일기
article thumbnail

❓Concurrency란 뭘까?

운영체제에서 Concurrency란 상당히 중요한 개념이다.

현대의 컴퓨터는 기본적으로 멀티코어 프로세서를 가지고 있기에 작업의 병렬 처리가 가능하다.

웹 브라우저에서 여러 웹 페이지를 동시에 로드하거나, 편집기에서 여러 문서를 동시에 편집하거나 등등.

 

concurrency(동시성) 란, 한 번에 여러 작업을 수행할 수 있는 컴퓨터 시스템의 능력을 가리키는

개념이다. OS로부터 각각 자원을 할당 받는 프로세스를 여러개 두고 관리하거나, 한 프로세스에서  자원을

공유하는 여러 스레드를 생산해 멀티 쓰레딩 프로그래밍을 하거나 할때에, concurrency는 빛을 발한다.

 

thread는 이렇게 한 프로세스의 stack 영역을 나누어 가지고, heap을 공유한다.

 

하지만 concurrency는 상당히 예민한 개념이다.

한 광산(프로세스)에서 여러명의 인부(스레드)가 작업을 하다보니, 서로 같은 데이터를 두고 다투는 경우가

일어날 수도 있기 때문이다. 이를 두고 Race Condition 이라는 개념이 등장한다.

 

❓Race Condition이란?

앞의 예시를 다시 들어보자.

한 광산에서 두 인부가 일하고 있었다. 광부들은, 회사에서 임무를 부여받고 광산으로 일을 하러간다.

회사에서는 게시판에 다음과 같은 작업을 공고했다.

즉 인부 A와 B는 합쳐서 5개의 광물만을 캐면 퇴근을 할 수 있는것이다!

이를 보고 인부 A와 B는, 약간의 시간차를 두고 각자 광산으로 출근을 했다.

인부 A는 현재 광물이 5개라는 사실만을 안 채로, 광물을 3개 캔 뒤 회사에

'현재 광물의 개수는 8개입니다' 라고 무전한다.

하지만 애석하게도, 간발의 차로 인부 B도 본사로부터 현재 광물이 8개라는 사실을 전해듣기 전에 5개라는

사실만을 안 채로, 광물을 2개 캔뒤 본사에

'현재 광물의 개수는 7개입니다'라는 무전을 한 것이다.

 

본사는 무전을 받는 족족 업데이트를 하는데,  '현재 광물의 개수는 8개입니다'  무전을 받은 뒤 광물의 개수를 8개라고 업데이트를 한다. 하지만 바로 직후 '현재 광물의 개수는 7개입니다' 무전을 받고, 현재 광물을 10개가 아닌 7개로 업데이트 하고 마는것이다.

 

이를 코드로 한 번 살펴보자.

예시의 모든 코드는 POSIX 스레드(pthread)로 작성하였다.

위 코드에서는 main 함수(회사)에서 pthread_create 함수로 p1과 p2 두개의  thread(광부)를 생성하고,

counter(광물)를 각각 1000000 만큼 증가시키는 '임무'를 맡긴다.

첫번째 경우처럼 인부 두명이 작업을 한 뒤 무전도 교차적으로 잘 이루어졌다면, 결과는 정상적으로

'2000000'개의 광물이 있다고 인지하겠지만,

앞서 말한 예시처럼 무전이 교차적으로 잘 일어나지 않았다면, 두번째 세번째 경우처럼 총 개수에

오차가 생기고 마는 것이다. 이를 두고 OS에서는 Race Condition이 일어났다고 한다.

 

이렇게 혼동이 일어날 수 있는 data 영역을 두고, Critical section 이라고 일컫는다. 

그리고 Critical section에서 발생하는 Race Condition을 방지해주는 것을 

Mutual exclusion (상호 배제)라고 한다.

 

Mutual exclusion을 구현하기 위해서는 

  • 세마포어 (semaphore)
  • 뮤텍스 (Mutex)
  • 모니터 (Monitor)

등의 기법을 사용할 수 있다.

 

❓Mutex란?

Mutex는 공유 자원에 대한 접근을 동시에 하나의 스레드만을 허용하게 한다.

Mutex는 lock과 unlock 연산을 사용해서, 내가 어떤 공유 자원을 사용하고자 할 때 다른 thread가

접근할 수 없도록 공유 자원에 대한 접근을 시도하는 critical section에 lock을 하고 연산을 한 뒤,

unlcok하여 다른 thread가 접근 가능하도록  잠금을 해제해준다.

위는 C에서 간단히 lock과 unlock을 사용하여 counter 공유 자원에 대해 하나의 thread만이

접근 가능하도록 구현한 스도코드이다.

ptread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER

위 코드가  C에서 Mutex를 선언하는 방법이다.

 

pthread_mutex_unlock(&lock);
int pthread_mutex_destroy(&lock);

사용이 끝난 Mutex는 위와 같은 destroy 함수로 삭제할 수 있다.

하지만 mutex를 사용중에 해제할 수도 있기 때문에 사용중인 mutex가 있다면

반드시 먼저 unlock 해주어야한다.

 

* 추가로, pthread를 사용하는 프로그램을  컴파일 할때는 반드시 마지막에 -pthread 옵션을 주어야 한다.

ex)

gcc -o main main.c -pthread

 

 

 

profile

만쥬의 개발일기

@KangManJoo

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!