πŸ’Ώμš΄μ˜μ²΄μ œ(동기화, μ„Έλ§ˆν¬μ–΄)

νŒ”λ¦¬λ™Β·2021λ…„ 5μ›” 10일
0

πŸ’½μš΄μ˜μ²΄μ œ(동기화, μ„Έλ§ˆν¬μ–΄, λ°λ“œλ½)

동기화 이슈(Synchronization) 이슈

사진 좜처: https://solt.tistory.com/78

  • 동기화: μž‘μ—…λ“€ 사이에 μ‹€ν–‰ μ‹œκΈ°λ₯Ό λ§žμΆ”λŠ” 것
  • μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μΌν•œ μžμ›(데이터) μ ‘κ·Όμ‹œ 동기화 이슈 λ°œμƒ
    • 동일 μžμ›μ„ μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œ μˆ˜μ •μ‹œ, 각 μŠ€λ ˆλ“œ 결과에 영ν–₯을 쀌

동기화 이슈 예제

import threading

g_count = 0

def thread_main():
    global g_count
    for i in range(1000000):
        g_count = g_count + 1 
    
threads = []
lock = threading.Lock()

for i in range(50):
    th = threading.Thread(target= thread_main)
    threads.append(th)

for th in threads:
    th.start()

for th in threads:
    th.join()

print('g_count = ', g_count)
  • νŒŒμ΄μ¬μ—μ„œ μ“°λ ˆλ“œλ₯Ό ν†΅μ œν•˜λŠ” 라이브러리λ₯Ό import ν–ˆλ‹€.
  • g_count λΌλŠ” μ „μ—­λ³€μˆ˜λ₯Ό μ„ μ–Έν•΄μ£Όκ³ 
  • 1λΆ€ν„° 100λ§ŒκΉŒμ§€ 1μ”© λ”ν•˜λŠ” 반볡문 ν•¨μˆ˜(thread_main)λ₯Ό μ •μ˜ν–ˆλ‹€
  • ν”„λ¦°νŠΈν•΄λ³΄λ©΄ 5천만이 λ‚˜μ˜€μ§€ μ•Šκ³  λ‹€λ₯Έ μˆ«μžκ°€ λ‚˜μ˜¨λ‹€.

μš΄μ˜μ²΄μ œκ°€ μ»¨ν…μŠ€νŠΈ μŠ€μœ„μΉ­μ„ν•΄μ„œ 백만의 반볡문이 μ‹€ν–‰λ˜λ‹€κ°€ μ“°λ ˆλ“œκ°€ 쀑간에 λ°”λ€Œμ–΄μ„œ μƒκΈ°λŠ” 일이닀.

ν•΄κ²° 방법

import threading

g_count = 0

def thread_main():
    global g_count
    lock.acquire()
    for i in range(1000000):
        g_count = g_count + 1 
    lock.release()
    
threads = []
lock = 
for i in range(50):
    th = threading.Thread(target= thread_main)
    threads.append(th)

for th in threads:
    th.start()

for th in threads:
    th.join()

print('g_count = ', g_count)
  • lock.acquire()λ₯Ό μ‚¬μš©ν•΄μ„œ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— λ°˜λ³΅λ¬Έμ— μ ‘κ·Όν•  λ•Œ ν•œκ°œμ˜ μŠ€λ ˆλ“œλ§Œ μ ‘κ·Όν•˜κ³  λ‚˜λ¨Έμ§€λŠ” λͺ»μ ‘κ·Όν•˜κ²Œ ν•œλ‹€.

  • λ°˜λ³΅λ¬Έμ— μ ‘κ·Όν•œ μŠ€λ ˆλ“œκ°€ λ‚˜μ˜€λ©΄μ„œ lock.release()ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•΄μ„œ λ‹€μŒ μŠ€λ ˆλ“œκ°€ λ°˜λ³΅λ¬Έμ— μ ‘κ·Όν•  수 있게 ν•œλ‹€.

동기화 이슈 ν•΄κ²° λ°©μ•ˆ

  • Mutual exclusion(μƒν˜Έ 배제)
  • μ“°λ ˆλ“œλŠ” ν”„λ‘œμ„ΈμŠ€μ˜ λͺ¨λ“  데이터λ₯Ό μ ‘κ·Όν•  수 μžˆμœΌλ―€λ‘œ,
    • μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ³€κ²½ν•˜λŠ” κ³΅μœ λ³€μˆ˜μ— λŒ€ν•΄ Exclusive Access ν•„μš”
    • μ–΄λŠ ν•œ μŠ€λ ˆλ“œκ°€ 곡유 λ³€μˆ˜λ₯Ό κ°±μ‹ ν•˜λŠ” λ™μ•ˆ λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λ„둝 λ§‰λŠ”λ‹€.

Mutual exclusion(μƒν˜Έ 배제)

    lock.acquire()
    for i in range(1000000):
        g_count = g_count + 1 
    lock.release()
  • 반볡문이 μž„κ³„μ˜μ—­(critical section)이고
  • g_count += 1 이 μž„κ³„μžμ›(critical resource)이닀.

동기화와 μ„Έλ§ˆν¬μ–΄

Mutex와 μ„Έλ§ˆν¬μ–΄ (Semaphore)

  • Critical Section(μž„κ³„κ΅¬μ—­)에 λŒ€ν•œ 접근을 막기 μœ„ν•΄ LOCKING λ§€μ»€λ‹ˆμ¦˜μ΄ ν•„μš”
    • Mutex(binary semaphore)
      : μž„κ³„κ΅¬μ—­μ— ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§Œ λ“€μ–΄κ°ˆ 수 있음
    • Semaphore
      : μž„κ³„κ΅¬μ—­μ— μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ“€μ–΄κ°ˆ 수 있음
      : counterλ₯Ό λ‘μ–΄μ„œ λ™μ‹œμ— λ¦¬μ†ŒμŠ€μ— μ ‘κ·Όν•  수 μžˆλŠ” ν—ˆμš© κ°€λŠ₯ν•œ μŠ€λ ˆλ“œ 수λ₯Ό μ œμ–΄

μ„Έλ§ˆν¬μ–΄(Semaphore)

  • P: 검사 (μž„κ³„μ˜μ—­μ— λ“€μ–΄κ°ˆ λ•Œ) -> lock.acquire()
    • S값이 1 이상이면, μž„κ³„ μ˜μ—­ μ§„μž… ν›„, Sκ°’ 1 차감 (S값이 0이면 λŒ€κΈ°)
P(s): wait(S) {
		while s <= 0 // λŒ€κΈ°
        S--; // λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€ μ ‘κ·Ό μ œν•œ (1κ°μ†Œ)
        }
  • V: 증가(μž„κ³„μ˜μ—­μ—μ„œ λ‚˜μ˜¬ λ•Œ) -> lock.release()
    • S값을 1λ”ν•˜κ³ , μž„κ³„ μ˜μ—­μ„ λ‚˜μ˜΄
V(S): signal(S) {
	s ++;  // λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€ μ ‘κ·Ό ν—ˆμš© (1증가)
    }
  • S: μ„Έλ§ˆν¬μ–΄ κ°’ (초기 κ°’λ§ŒνΌ μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€κ°€ λ™μ‹œ μž„κ³„ μ˜μ—­ μ ‘κ·Ό κ°€λŠ₯)

μ„Έλ§ˆν¬μ–΄(Semaphore)- λ°”μœ λŒ€κΈ°

  • wait()은 Sκ°€ 0이라면, μž„κ³„μ˜μ—­μ— λ“€μ–΄κ°€κΈ° μœ„ν•΄, 반볡문 μˆ˜ν–‰
    • λ°”μœλŒ€κΈ°, busy waiting -> 멈좀이 μ—†λ‹€. -> CPU에 λΆ€ν•˜λ₯Ό 걸리게 함
P(s): wait(S) {
		while s <= 0 // λŒ€κΈ°
        S--; // λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€ μ ‘κ·Ό μ œν•œ (1κ°μ†Œ)
        }

μ„Έλ§ˆν¬μ–΄(Semaphore) - λŒ€κΈ°ν

  • Sκ°€ 음수일 경우, λ°”μœ λŒ€κΈ° λŒ€μ‹ , λŒ€κΈ°νμ— λ„£λŠ”λ‹€.
wait(S) {
    	S->count--;
    if (S->count <= 0) {
    	add this process to S->queue; // λŒ€κΈ° 
        block() // 블둝, sleap()
    }
}
  • wakeup() ν•¨μˆ˜λ₯Ό 톡해 λŒ€κΈ°νμ— μžˆλŠ” ν”„λ‘œμ„ΈμŠ€ μž¬μ‹€ν–‰
signal(s) {
		S->count++;
    if (S->count >=1) {
        remove a process P form S->queue;
        wakeup(P) // 깨우기
    }
}

μ°Έκ³ : μ£Όμš” μ„Έλ§ˆν¬μ–΄ ν•¨μˆ˜(POSIX μ„Έλ§ˆν¬μ–΄)

  • sem_open(): μ„Έλ§ˆν¬μ–΄λ₯Ό 생성
  • sem_wait(): μž„κ³„μ˜μ—­ μ ‘κ·Ό μ „, μ„Έλ§ˆν¬μ–΄λ₯Ό 잠그고, μ„Έλ§ˆν¬μ–΄κ°€ μž κ²¨μžˆλ‹€λ©΄, 풀릴 λ•ŒκΉŒμ§€ λŒ€κΈ°
  • sem_post(): κ³΅μœ μžμ›μ— λŒ€ν•œ 접근이 끝났을 λ•Œ μ„Έλ§ˆν¬μ–΄ μž κΈˆμ„ ν•΄μ œν•œλ‹€.
profile
λ°°μ›€μ˜ 기둝

0개의 λŒ“κΈ€