관리 메뉴

Unfazedβ—οΈπŸŽ―

μŠ€λ ˆλ“œ μ•ˆμ „μ„± Thread Safety λ³Έλ¬Έ

Operating System (운영체제)

μŠ€λ ˆλ“œ μ•ˆμ „μ„± Thread Safety

9taetae9 2024. 1. 29. 20:27
728x90

Thread safety

μŠ€λ ˆλ“œ μ•ˆμ „μ„±μ€ μ—¬λŸ¬ μŠ€λ ˆλ“œμ— μ˜ν•΄ λ™μ‹œμ— μ‹€ν–‰λ˜λŠ” κ²½μš°μ—λ„ μ•Œκ³ λ¦¬μ¦˜μ΄λ‚˜ μ½”λ“œ 뢀뢄이 μ˜¬λ°”λ₯΄κ²Œ λ™μž‘ν•  수 μžˆλŠ” μ„±μ§ˆμ„ λ§ν•œλ‹€. μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— μ½”λ“œλ₯Ό 싀행해도 데이터 μ†μƒμ΄λ‚˜ μ˜ˆμƒμΉ˜ λͺ»ν•œ 행동이 λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ μŠ€λ ˆλ“œμ— μ•ˆμ „ν•˜λ‹€κ³  ν•  수 μžˆλ‹€.

이에 λ°˜ν•΄, μŠ€λ ˆλ“œ μ‹€ν–‰μ˜ μˆœμ„œλ‚˜ 타이밍에 따라 κ²°κ³Όκ°€ λ‹¬λΌμ§€λŠ” 경쟁 μƒνƒœμ™€ 같은 λ¬Έμ œκ°€ λ°œμƒν•œλ‹€λ©΄ μŠ€λ ˆλ“œμ— μ•ˆμ „ν•˜μ§€ μ•Šλ‹€. μŠ€λ ˆλ“œμ— μ•ˆμ „ν•˜μ§€ μ•Šμ€ μ½”λ“œλŠ” λ™μ‹œμ— λ˜λŠ” λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ μ•ˆμ „ν•˜κ²Œ μ‚¬μš©ν•  수 μ—†κ²Œ λœλ‹€.

 

λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ count λ³€μˆ˜λ₯Ό μ‚¬μš©ν•œ μ˜ˆμ‹œλ₯Ό 보자.

0으둜 μ΄ˆκΈ°ν™”λœ count λ³€μˆ˜κ°€ 있고 2개의 μŠ€λ ˆλ“œκ°€ 'increment()' λ©”μ†Œλ“œλ₯Ό λ™μ‹œμ— ν˜ΈμΆœν•˜λŠ” 상황을 생각해 보자

public class Counter{

    private int count = 0;


    public void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

 

κ²°λ‘ λΆ€ν„° λ§ν•˜λ©΄ ν•΄λ‹Ή ν΄λž˜μŠ€λŠ” λ©€λ¦¬μŠ€ν…Œλ“œ ν™˜κ²½μ—μ„œ μŠ€λ ˆλ“œ μ•ˆμ „ν•˜μ§€ μ•Šλ‹€. 예λ₯Ό λ“€μ–΄, 두 μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— 'count'값을 μ½μ—ˆμ„ λ•Œ 같은 값을 μ–»κ³ , λ‘˜ λ‹€ ν•΄λ‹Ή 값을 1 μ¦κ°€μ‹œν‚¨λ‹€λ©΄, μ‹€μ œλ‘œλŠ” 2만큼 증가해야 λ˜μ§€λ§Œ countκ°€ 1만 μ¦κ°€ν•˜λŠ” 상황이 λ°œμƒν•  수 μžˆλ‹€.

 

μžλ°”μ—μ„œλŠ” 동기화(synchronized)λ₯Ό μ‚¬μš©ν•΄μ„œ 이 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλ‹€.

public class ThreadSafeCounter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

 

각 λ©”μ†Œλ“œμ— 'synchronized' ν‚€μ›Œλ“œλ₯Ό μΆ”κ°€μ‹œν‚€λ©΄, ν•΄λ‹Ή μ‹œμ μ— 였직 ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§Œ ν•΄λ‹Ή λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•  수 있게 λœλ‹€. λ™μ‹œμ— μ ‘κ·Όν•  수 μžˆλŠ” 상황이 μžƒμ–΄λ‚˜μ§€ μ•Šκ²Œ λ˜λ―€λ‘œ 이제 ν•΄λ‹Ή ν΄λž˜μŠ€λŠ” μŠ€λ ˆλ“œμ— μ•ˆμ „ν•˜λ‹€κ³  ν•  수 μžˆλ‹€.

λ‹€λ§Œ 'synchronized'λŠ” μ„±λŠ₯ μ €ν•˜κ°€ λ°œμƒν•  수 있기 λ•Œλ¬Έμ— ν•„μš”ν•œ μƒν™©μ—λ§Œ μ‚¬μš©ν•˜λŠ” 것이 ꢌμž₯λœλ‹€.

더 λ³΅μž‘ν•œ μƒν™©μ—μ„œλŠ” 'ReentrantLock', 'AtomicInteger' λ“±κ³Ό 같은 λ™μ‹œμ„± μ œμ–΄ λ©”μ»€λ‹ˆμ¦˜μ„ μ‚¬μš©ν•˜λŠ” 방법도 κ³ λ €ν•΄ λ³Ό 수 μžˆλ‹€.

 

 'synchronized'ν‚€μ›Œλ“œλŠ” λ©”μ†Œλ“œ μ „μ²΄λ‚˜ νŠΉμ • 블둝에 μ μš©ν•  수 있고,  'synchronized' λΈ”λ‘μ΄λ‚˜ λ©”μ†Œλ“œλ₯Ό λ²—μ–΄λ‚˜λ©΄ μžλ™μœΌλ‘œ 잠금이 ν•΄μ œλœλ‹€λŠ” κ°„νŽΈν•¨μ΄ μžˆμ§€λ§Œ, μ„Έλ°€ν•œ 쑰건에 따라 μž κΈˆμ„ λŒ€κΈ°ν•˜κ±°λ‚˜ ν•΄μ œν•˜λŠ” κΈ°λŠ₯을 λ‚΄μž₯ν•˜κ³  μžˆμ§€ μ•Šλ‹€.

 

ReentrantLockλŠ” lock()κ³Ό unlock() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 더 μ„Έλ°€ν•œ μ œμ–΄κ°€ κ°€λŠ₯ν•œλ°, λͺ…μ‹œμ μœΌλ‘œ 'unlock()'ν˜ΈμΆœμ„ 톡해 μˆ˜λ™μœΌλ‘œ μž κΈˆμ„ ν•΄μ œν•΄μ£Όμ–΄μ•Ό ν•œλ‹€. μ„Έλ°€ν•œ μ œμ–΄λ₯Ό μœ„ν•΄ 'Condition' μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ νŠΉμ • μ‘°κ±΄μ—μ„œμ˜ λŒ€κΈ° 및 μ•Œλ¦Όμ΄ κ°€λŠ₯ν•˜λ‹€. λ˜ν•œ, μŠ€λ ˆλ“œ λŒ€κΈ° μˆœμ„œλ₯Ό 보μž₯, 잠금 μ‹œλ„ μ‹œ λŒ€κΈ° μ‹œκ°„ μ„€μ •, 잠금 μƒνƒœ 검사 λ“± 좔가적인 κΈ°λŠ₯도 μ œκ³΅ν•œλ‹€.

 

Atomic 클래슀 

μžλ°”μ—μ„œ 'Atomic' ν΄λž˜μŠ€λ“€μ„ μ›μžμ  연산을 톡해 μŠ€λ ˆλ“œ μ•ˆμ „μ„ 보μž₯ν•œλ‹€.

μ›μžμ  μ—°μ‚°(atomic)μ΄λž€ 연산이 쀑간 단계 없이 λκΉŒμ§€ μˆ˜ν–‰λ˜λŠ” 것을 μ˜λ―Έν•œλ‹€. 즉, μ—°μ‚° 쀑 λ‹€λ₯Έ μŠ€λ ˆλ“œμ—κ²Œ λ°©ν•΄λ°›μ§€ μ•Šμ„ 수 있게 λœλ‹€. 예λ₯Ό λ“€μ–΄ 'AtomicInteger'의 'incrementAndGet()'λ©”μ†Œλ“œλŠ” λ³€μˆ˜μ˜ 값을 μ•ˆμ „ν•˜κ²Œ μ¦κ°€μ‹œν‚€κ³ , μ¦κ°€λœ 값을 λ°˜ν™˜ν•œλ‹€.

 

 

 

μΆ”κ°€μ μœΌλ‘œ Collection ν΄λž˜μŠ€λ“€μ—μ„œλ„ thread safeν•œ ν΄λž˜μŠ€μ™€ μŠ€λ ˆλ“œμ— μ•ˆμ „ν•˜μ§€ μ•Šμ€ ν΄λž˜μŠ€κ°€ μžˆλ‹€. 예λ₯Ό λ“€μ–΄ Vectorκ°€ μŠ€λ ˆλ“œμ— μ•ˆμ „(thread safe)ν•˜κ³  ArrayListκ°€ μŠ€λ ˆλ“œμ— μ•ˆμ „ν•˜μ§€ μ•Šλ‹€. 

즉, ArrayListλŠ” μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— 값을 λ³€κ²½ν•˜λŠ” 상황에 μ·¨μ•½ν•  수 μžˆλ‹€.

 

λ§Œμ•½ ArrayListλ₯Ό μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ λ™μ‹œμ— μž‘μ—…μ„ 해도 μ•ˆμ „ν•˜κ²Œ λ§Œλ“€κ³  μ‹Άλ‹€λ©΄ μ•„λž˜μ™€ 같이 객체λ₯Ό 생성할 수 μžˆλ‹€.

List list = Collections.synchronizedList(new ArrayList(...)); 

 

VectorλŠ” μžλ°”μ˜ 초기 버전뢀터 제곡된 클래슀둜, λ‚΄λΆ€μ˜ λͺ¨λ“  μ£Όμš” λ©”μ†Œλ“œλ“€μ΄ 이미 'synchronized'둜 μ„ μ–Έλ˜μ–΄ μžˆλ‹€. κ·ΈλŸ¬λ‚˜ λͺ¨λ“  λ©”μ†Œλ“œμ— 'synchronized'λ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ—, vectorλŠ” μƒλŒ€μ μœΌλ‘œ μ˜€λ²„ν—€λ“œκ°€ μ»€μ„œ μŠ€λ ˆλ“œ 경합이 μ‹¬ν•œ λ©€ν‹° μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ μ„±λŠ₯ μ €ν•˜κ°€ λ°œμƒν•  수 μžˆλ‹€.

 

Collections.synchronizedListλŠ” ν•„μš”ν•œ λΆ€λΆ„μ—λ§Œ 동기화λ₯Ό μ μš©ν•  있기 λ•Œλ¬Έμ—, μ΄λŸ¬ν•œ μ˜€λ²„ν—€λ“œλ₯Ό 쀄일 수 μžˆλ‹€. λ”°λΌμ„œ λ³‘λ ¬μ²˜λ¦¬μ™€ κ΄€λ ¨λœ μ„±λŠ₯ μ΅œμ ν™”κ°€ ν•„μš”ν•œ 경우 λ“±, ν™•μž₯μ„± μΈ‘λ©΄μ—μ„œ vector μ‚¬μš©λ³΄λ‹€ 더 μœ λ¦¬ν•˜λ‹€.

728x90