[전공 CS]/[컴퓨터 구조론][운영체제]

[운영체제] 6장 스레드 동기화

우당탕탕 개발 일지 2025. 12. 8. 14:44
728x90

수업에 나온 내용을 바탕으로 정리한 내용입니다. 명품 운영체제의 내용이 포함되어 있습니다. 

 

 

 

ch01 스레드 동기화의 필요성

 

스레드 동기화  : 공유데이터에 대한 다수의 스레드의 동시 접근을 해결하는 방법.

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

 

 

필요 이유 )

두 스레드가 동시에 공유데이터에 write하는 경우 공유 데이터에 훼손이  발생할 수 있기 때문 

 

 

해결 방법 )  사용 중일때 lock을 걸어줌.

한 스레드가 공유 데이터 사용을 마칠 때까지, 다른 스레드가 공유 데이터에 접근하지 못하도록 제어.


ch02 상호배제 

임계구역 : 공유 데이터에 접근하는 코드 블록. 

상호 배제 : 임계구역이 한 스레드만 배타적 독점적으로 실행하도록 보장하는 것. 

 

→임계구역은 반드시 상호 배제와 함께 해야함. 

 

공유데이터를 다루는 멀티 스레드 프로그램의 모습

1. 일반 코드(non-critical code)

: 공유 데이터를 액세스하지 않는 코드

 

 

2. 임계구역 진입 코드(entry code)

임계구역에 진입하기 전 필요한 코드 블록

현재 임계구역을 실행 중인 스레드가 있는지 검사

없다면, 다른 스레드가 들어오지 못하도록 조치 (내꺼 실행할거임!) 

있다면, 진입이 가능해질 때까지 대기 (lock)

 

 

 

3. 임계구역 코드(critical code)

: 공유 데이터에 접근하는 코드 블록

(임계 구역이 짧을 수록 좋음)

 

 

4. 임계구역 진출 코드(exit code)

: 임계구역을 마칠 때 필요한 코드 블록

대기중인 스레드가 임계구역에 진입할 수 있도록, 진입 코드에서 취한 조치 해제 (lock해제)

 

 

 


 

상호배제 구현 

구현 목표 : 임계구역에 오직 한 스레드만 들어가게 하는 방책.

소프트웨어적 : Peterson's 알고리즘
하드웨어적:  인터럽트 서비스 금지 , 원자 명령(오늘날 사용) ⭐️

 

 

1. 인터럽트 서비스 금지

entry code에서 인터럽트 서비스를 금지 시키고 

exit code에서 인터럽트 서비스를 허용하는 CPU 명령들을 실행하는 방법.

 

 

동작 방식 ) 

cli entry 코드. 인터럽트 서비스 금지 명령 cli(clear interrupt flag) IF(0)
sti exit 코드. 인터럽트 서비스 허용 명령 sti(set interrupt flag) IF(1)

 

 

 

문제점 )

(1) 임계 구역을 실행하는 동안 모든 인터럽트가 무시됨. 

임계구역의 실행 시간이 길어지게 되면 중요한 ISR을 실행 못할 수도 있음.  

 

(2)해당 방법은 단일 CPU에서만 사용 가능함. 

멀티 코어 CPU 다중 CPU에서는 사용 X

 

 

 

 

2. 원자 명령 (TSL) 

*test and set lock

 

원자 명령이 필요한 이유) 

  • lock변수 0,1로 상호 배제를 구현하면 얼핏 성공한 것처럼 보여도 실패하는 경우가 생김.
  • lock값을 읽는 명령과 lock을 1로 바꾸는 명령이 하나의 단위로 실행되지 않아 컨텍스트 스위칭이 발생하면서 실패함. (p308~309)

 

 

원자명령 : lock값을 읽는 명령과  lock을 1로 바꾸는 명령을  하나의 단위로 만드는 것. 

→ TSL은 entry code임. 

mov ax, lock   TSL ax, lock
mov lock,1

※ 원자 명령은 도중에 ISR이나 컨텍스트 스위칭이 발생 하지 않음 

 

 


ch 03 멀티 스레드 동기화 기법 ( =동기화 프리미티브 )

: 상호배제 기반 위에 여러 스레드를 문제 없이 공유 자원을 활용 하도록 하는  기법.

 

  • lock : 뮤텍스, 스핀락 
  • wait-signal : 세마포 

 

1. 뮤텍스 (mutex)

락 변수  잠김/ 열림(unlocked) 중 한 상태를 가지는 변수 (T/F)
lock/unlock 연산  lock : entry code |  unlock : exit code
대기큐 ⭐️⭐️⭐️ 임계 구역에 있지 않는 나머지 스레드는 큐에 삽입.

 

※뮤텍스에서 unlock을 blocking lock 이나 sleep-waitong lock(수면대기락) 이라고도 함.

대기 큐로 갔다가 다시 임계구역으로 갈때 2번의 컨텍스트 스위칭 발생

 

실행 시간이 짧은 경우 뮤텍스틑 비효율적임. (2번의 컨텍스트 스위칭이 발생하기 때문)

  • 단일 코어 CPU에 적합 
  • 주 사용처 : 사용자 응용 프로그램 
  • 블록 가능 여부 : 락이 잠겨 있으면 블록됨
  • 연산비용 : 저비용 

 

 


 

2. 스핀락 (spinlock)

★뮤텍스와 같은 락 기반이지만 대기큐가 없음. 

 

락이 잠겨 있으면  열릴때까지  락 검사를 무한 반복함.

타임 슬라이스가 소진 되면  컨텍스트 스위칭되고 다시 락이 풀릴 때까지 검사를 반복함

락 변수  잠김/ 열림(unlocked) 중 한 상태를 가지는 변수 (T/F)
lock/unlock연산  lock : entry code |  unlock : exit code

※스핀락에서 unlock을  busy-waiting lock(바쁜 대기락) 이라고도 함.

 

 

단일 cpu를 가진 운영체제에서는 스핀락이 매우 비효율적임. (멀티코어 CPU에 적합

스핀락은 임계 구역 코드가 짧아  락이 빨리 열리는 곳에 효과적임 

스핀락은 스레드들이 락을 얻기 위해 무한 경쟁하기 때문에 기아가 발생할 수 있음. 

 

  • 주 사용처 : 커널코드, ISR
  • 블록 가능 여부 :  X ( 잠겨 있어도 계속 락 검사진행) 
  • 연산 비용 : 고비용 (계속 CPU를 사용함)

 


3. 세마포 ( semaphore)

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

 

 

세마포가 필요한 상황

 

 

 

자원  n개 
대기큐  자원을 할당 받지 못한 스레드가 있는 곳
counter 변수  사용 가능한 자원의 개수를 나타내는 정수형 변수 (음수면 자원을 기다리는 스레드의 개수 ) 
P/V 연산 (wait /signal)  P : 자원 요청시 counter 변수를 -1 시킴  | V : 자원 반환시 counter변수를 +1시킴

 

 

T1일때 counter =3 -- T4일때는 counter=0

 

 

 

※ sleep-wait 와 busy-waiting 두가지 종류 중 하나 사용. 

 

 

 

● 카운터 세마포 : 자원이 여러개인 경우  ( 앞에 설명한 경우)

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

이진 세마포 
세마포 변수 S 0과 1중 하나를 가지는 변수 (1로 초기화 됨) 
대기큐  스레드가 대기하는 큐 
P 연산 (wait) 자원 사용허가를 얻는 과정. S를 1만큼 감소 [ 0보다 크면 실행, 0보다 작으면 대기큐에서 잠들게]
V 연산 (signal) 자원 사용이 끝났음을 알리는 과정. S를 1만큼 증가 [ 0보다 크면 리턴, 0보다 작으면 대기큐에서 하나 불러와 실행]

 

 

 


4. 우선순위 역전 

: 스레드 동기화로 인해 우선순위가 높은 스레드가 순위가 낮은 스레드보다 늦게 실행되는것. 

 

 

해결책 ( 두 방법 모두 구현이 쉽지 않고 오버헤드 존재함)

 

1) 우선 순위 올림  (priority ceiling)

낮은 우선순위가 공유 자원을 소유하게 될때 일시적으로 미리 정해둔 순위로 올리는것. 

실행이 끝난 뒤에 원래 우선 순위대로 실행됨. 

 

2) 우선 순위 상속 (priority inheritance)

낮은 우선 순위 스레드가  공유자원을 가지는 동안 높은 순위 스레드가 공유자원 요청을 하면 

낮은 순위 스레드를 높은 순위 스레드 보다 높게 설정함.  

실행이 끝난 뒤 원래 우선 순위대로 실행됨. 

 

 


Ch04 생산자 소비자 문제 ( 동기화 문제 중 하나 )

생산자 : 공유 버퍼에 데이터를 공급하는 사람. 

소비자 : 공유 버퍼에 데이터를 읽는 사람. 

 

생산자 소비자 문제(= 실행 순서 제어 ) : 공유버퍼를 문제 없이 사용하도록 생산자와 소비자를 동기화 시키는 문제.

 

 

문제  상황 해결
상호배제   뮤텍스나 세마포 이용 
비어 있는 공유버퍼 (소비자가 쓸때) 세마포 R활용 (R: 읽기 가능한 버퍼 개수, 0이면 대기) 

→소비자가 잠깐 대기, 생상자가  쓰고 소비자 깨움
꽉 판 공유버퍼 (생산자가 쓸때) 세마포 W활용 ( W :쓰기 가능한 버퍼 개수, 0이면 대기 )

→ 생산자 잠깐 대기, 소비자가  사용하고 생산자 깨움 

※ M : 뮤텍스. 생산자 소비자 모두 사용