ν‹°μŠ€ν† λ¦¬ λ·°

728x90
λ°˜μ‘ν˜•

 ν”„λ‘œμ„ΈμŠ€ κ°„μ˜ 정보λ₯Ό μ£Όκ³  λ°›κ±°λ‚˜, ν•˜λ‚˜μ˜ 곡유된 μ˜μ—­μ„ μ‚¬μš©ν•  κ²½μš°μ—λŠ” μ£Όμ˜κ°€ ν•„μš”ν•˜λ‹€. 예λ₯Ό λ“€μ–΄ ν”„λ‘œμ„ΈμŠ€ AλŠ” 1λ²ˆμ§€ λ©”λͺ¨λ¦¬ 곡간에 10μ΄λΌλŠ” 값을 읽어 μ˜€κ³ μžν•˜μ˜€μœΌλ‚˜, ν”„λ‘œμ„ΈμŠ€ Bκ°€ ν”„λ‘œμ„ΈμŠ€ Aκ°€ μ½λŠ” 직전에 20μ΄λΌλŠ” κ°’μœΌλ‘œ λ³€κ²½ν•΄ 버리면 μ›ν•˜μ§€ μ•ŠλŠ” 값이 λ°˜ν™˜λ˜λŠ” κ²°κ³Όκ°€ λ°œμƒν•œλ‹€. μ΄λ ‡κ²Œ μƒν˜Έμ μœΌλ‘œ 영ν–₯을 λ―ΈμΉ˜λŠ” ν”„λ‘œμ„ΈμŠ€λ“€μ„ Cooperating Process라고 ν•œλ‹€. 이와 λ°˜λŒ€μΈ 경우 Independent Process라고 ν•œλ‹€.

 

 κ° ν”„λ‘œμ„ΈμŠ€λ‘œ 인해 곡유 λ°μ΄ν„°μ˜ 일관성을 보μž₯ν•˜μ§€ λͺ»ν•˜λŠ” 것을 막기 μœ„ν•΄ 동기화(Synchronization)κ°€ ν•„μš”ν•˜λ‹€. μ•žμ„œ λ§ν•œ κ°„λ‹¨ν•œ μ˜ˆμ‹œμ—μ„œ μ›μΉ˜ μ•ŠλŠ” 값을 λ°˜ν™˜λ°›μ§€ μ•ŠμœΌλ €λ©΄, ν”„λ‘œμ„ΈμŠ€ A → ν”„λ‘œμ„ΈμŠ€ B의 μˆœμ„œλ₯Ό 보μž₯ν•  경우 이와 같은 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλ‹€. 이 뿐만 μ•„λ‹ˆλΌ, 곡유 데이터λ₯Ό ν•œλ²ˆμ— ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€λ§Œ μ ‘κ·Όν•  수 μžˆλŠ” 방식을 μ‚¬μš©ν•˜μ—¬ 문제λ₯Ό ν•΄κ²°ν•  수 도 μžˆλ‹€.

 

Bank Account Problem (은행 κ³„μ’Œ 문제)

 λ™κΈ°ν™” 문제 쀑 μ§κ΄€μ μœΌλ‘œ 이해할 수 있고, λŒ€ν‘œμ μΈ λ¬Έμ œκ°€ 은행 κ³„μ’Œμ— κΈˆμ•‘μ΄ μž…μΆœκΈˆ 될 κ²½μš°μ΄λ‹€. λ§Œμ•½ μž…μΆœκΈˆ κ³Όμ •μ˜ μˆœμœ„κ°€ 보μž₯λ˜μ§€ μ•ŠλŠ”λ‹€λ©΄, μ›μΉ˜ μ•ŠλŠ” κ²°κ³Όλ₯Ό μ΄ˆλž˜ν•˜κ²Œ 될 것이닀.

 

class BankAccount {
    int balance;
    void deposit(int amount) {
        balance += amount;
    }

    void withdraw(int amount) {
        balance -= amount;
    }

    int getBalance() {
        return balance;
    }
}

class Parent extends Thread {
    BankAccount b;
    int count;
    Parent(BankAccount b, int count) {
        this.b = b;
        this.count = count;
    }

    public void run() {
        for (int i = 0; i < count; i++)
            b.deposit(1);
    }
}

class Child extends Thread {
    BankAccount b;
    int count;
    Child(BankAccount b, int count) {
        this.b = b;
        this.count = count;
    }

    public void run() {
        for (int i = 0; i < count; i++)
            b.withdraw(1);
    }
}


public class Test {
    static final int MAX = 100;
    public static void main(String[] args) throws InterruptedException {
        // 은행 κ³„μ’Œ 객체 생성
        BankAccount b = new BankAccount();
        // μ“°λ ˆλ“œ 객체 생성
        Parent p = new Parent(b, MAX);
        Child c = new Child(b, MAX);
        // μ“°λ ˆλ“œ μ‹€ν–‰
        p.start();
        c.start();
        p.join();
        c.join();
        // μž”μ•‘ 좜λ ₯
        System.out.println("Final balance = " + b.getBalance());
    }
}

 μœ„μ˜ κ°„λ‹¨ν•œ μžλ°” μ½”λ“œμ™€ 같이 μž…κΈˆμ„ ν•˜λŠ” 객체인 Parent와 μΆœκΈˆμ„ ν•˜λŠ” 객체인 Childκ°€ BanckAccountλΌλŠ” κ³΅μš©μžμ›μ„ μ‚¬μš©ν•˜κ³  μžˆλ‹€. 예제 μ½”λ“œλŠ” μ‹¬ν”Œν•˜μ—¬ λ‘κ°œμ˜ μ“°λ ˆλ“œκ°€ κ³΅μš©μžμ›μ„ μ‚¬μš©ν•˜λ©° 상황에 따라 μ›μΉ˜μ•ŠλŠ” κ²°κ³Όκ°€ λ‚˜μ˜¬ 수 μžˆλ‹€. 외와 같은 μ΄μœ λŠ” μž…μΆœκΈˆμ— λŒ€ν•œ μˆœμ„œκ°€ 보μž₯λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€. (μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ 맀 μ‹€ν–‰λ§ˆλ‹€ μž…μΆœκΈˆμ˜ μˆœμ„œκ°€ λ‹€λ₯΄κ²Œ 좜λ ₯λ˜λŠ” 것을 μ•Œ 수 μžˆλ‹€.)

 

μž„κ³„ ꡬ역 (Critical Section)

 μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€(μ“°λ ˆλ“œ)κ°€ μ‚¬μš©ν•˜λŠ” κ³΅μœ μžμ›μ— λŒ€ν•œ 변경이 λ°œμƒν•˜λŠ” μ½”λ“œ μ˜μ—­μ„ μž„κ³„ ꡬ역이라고 ν•œλ‹€. 은행 κ³„μ’Œ 문제 μ½”λ“œμ—μ„œλŠ” deposit, withdraw λ©”μ†Œλ“œκ°€ 이에 ν•΄λ‹Ήν•œλ‹€.

 

μž„κ³„ ꡬ역에 μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€(μ“°λ ˆλ“œ)κ°€ μ§„μž…ν•˜λ”λΌλ„ λ°μ΄ν„°μ˜ 일관성을 보μž₯ν•˜κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같은 쑰건을 λ§Œμ‘±μ‹œν‚¬ ν•„μš”κ°€ μžˆλ‹€.

  1. Mutual Exculsion : μž„κ³„ ꡬ역에 ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€(μ“°λ ˆλ“œ)κ°€ μ§„μž…ν•œ μƒνƒœλΌλ©΄ λ‹€λ₯Έ μ“°λ ˆλ“œλŠ” μ§„μž… ν•  수 μ—†λ‹€.

  2. Progess : 1의 쑰건을 μΆ©μ‘±μ‹œν‚€κΈ° μœ„ν•΄, μž„κ³„ ꡬ역에 μ ‘κ·Όν•˜κΈ° μœ„ν•œ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€(μ“°λ ˆλ“œ)듀은 λŒ€κΈ°κ°€ ν•„μš”ν•  것이닀. λ”°λΌμ„œ μž„κ³„ κ΅¬μ—­μ˜ λ™μž‘μ€ κ°„λ‹¨ν•˜κ³  짧은 μ‹œκ°„ 내에 이루어져야 ν•œλ‹€.

  3. Bounded Wating : μž„κ³„ ꡬ역을 μ§„μž…ν•˜λŠ” ν”„λ‘œμ„ΈμŠ€(μ“°λ ˆλ“œ)λŠ” 일정 μ‹œκ°„ 내에 μ§„μž…ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€.

 

ν”„λ‘œμ„ΈμŠ€(μ“°λ ˆλ“œ) 동기화

μ•žμ„œ λ°œμƒν•˜λŠ” λ™μ‹œμ— μž„κ³„κ΅¬μ—­μ— μ ‘κ·Όν•˜λŠ” 문제둜 인해 λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œλŠ” 동기화가 ν•„μš”ν•˜λ‹€. 동기화λ₯Ό 톡해 ν”„λ‘œμ„ΈμŠ€μ˜ μ‹€ν–‰ μˆœμ„œλ₯Ό μ œμ–΄ ν•  수 있으며, μž„κ³„ ꡬ역 μ§„μž…μ„ μœ„ν•œ λΆˆν•„μš”ν•œ Wating을 μ œκ±°ν•  수 μžˆλ‹€.

 

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

 μž„계 ꡬ역에 μ§„μž…ν•˜κΈ° μœ„ν•΄, μž„κ³„ ꡬ역에 μ§„μž…ν•  수 μžˆλŠ” κΆŒν•œμ„ νšλ“ν•˜κ³  κΆŒν•œμ„ νšλ“ν•œ κ²½μš°μ—λ§Œ μž„κ³„ ꡬ역에 μ§„μž…ν•  수 μžˆλ„λ‘ ν•˜λŠ” 동기화 방식을 λ§ν•œλ‹€. μžλ°”μ˜ 경우 μ“°λ ˆλ“œ μ‚¬μš© μ‹œ java.util.concurrent.Semaphoreλ₯Ό 톡해 μ„Έλ§ˆν¬μ–΄ 객체λ₯Ό μƒμ„±ν•˜μ—¬, μž„κ³„ κ΅¬μ—­μ˜ 문제λ₯Ό 방지할 수 μžˆλ‹€.

 

BankAccount Problem (USE Semaphore)

import java.util.concurrent.Semaphore;

class BankAccount {
    int balance;
    Semaphore s;

    BankAccount() {
        s = new Semaphore(1);
    }

    void deposit(int amount) {
        try {
            s.acquire();
        } catch (InterruptedException e) { }

        balance += amount;

        s.release();
    }

    void withdraw(int amount) {
        try {
            s.acquire();
        } catch (InterruptedException e) { }
        
        balance -= amount;

        s.release();
    }

    int getBalance() {
        return balance;
    }
}

λ™μ‹œμ— μ—¬λŸ¬ μ“°λ ˆλ“œκ°€ μž„κ³„ ꡬ역에 μ ‘κ·Όν•˜λŠ” 것을 막기 μœ„ν•΄ μžλ°”μ—μ„œλŠ” μœ„μ™€ 같이 κ΅¬ν˜„ν•  수 μžˆλ‹€. κΈ°μ‘΄ μ½”λ“œμ™€ 달리 BackAccount Generatorμ—μ„œ μ„Έλͺ¨ν¬μ–΄ 객체λ₯Ό ν• λ‹Ήν•˜κ³ , ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ§Œ μ ‘κ·Όν•  수 있게 permits의 값을 1둜 μ„€μ •ν•œλ‹€. λ˜ν•œ, depositκ³Ό withdraw ν•¨μˆ˜κ°€ 호좜되면, μ„Έλͺ¨ν¬μ–΄λ₯Ό νšλ“/ ν•΄μ œ ν•˜λŠ” μ½”λ“œλ₯Ό 톡해 μž„κ³„ ꡬ역에 ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ§Œ μ ‘κ·Όν•  수 μžˆλ„λ‘ ν•  수 μžˆλ‹€.

 

Ordering

 λ‹¨μˆœνžˆ μ„Έλͺ¨ν¬μ–΄λ₯Ό μ μš©ν•  경우의 λ¬Έμ œμ μ€ μ—¬μ „νžˆ μž…μΆœκΈˆμ— λŒ€ν•œ μˆœμ„œλ₯Ό 보μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ μ‹€μ œ 상황와 λΉ„μŠ·ν•˜κ²Œ μž…μΆœκΈˆμ— λ”°λ₯Έ μˆœμ„œλ₯Ό 보μž₯μ‹œν‚€κΈ° μœ„ν•΄μ„œλŠ” λ‹€μŒκ³Ό 같은 과정이 ν•„μš”ν•˜λ‹€.

 

class BankAccount {
    int balance;
    Semaphore critical;
    Semaphore order;

    BankAccount() {
        critical = new Semaphore(1);
        order = new Semaphore(0);
    }

    void deposit(int amount) {
        try {
            critical.acquire();
        } catch (InterruptedException e) { }

        balance += amount;

        critical.release();
        order.release();
    }

    void withdraw(int amount) {
        try {
            order.acquire();
            critical.acquire();
        } catch (InterruptedException e) { }

        balance -= amount;

        critical.release();
    }

    int getBalance() {
        return balance;
    }
}

 μž„계 ꡬ역에 λŒ€ν•œ 접근은 μ„Έλͺ¨ν¬μ–΄ νšλ“ / ν•΄μ œλ₯Ό 톡해 보μž₯ν•˜μ˜€λ‹€. μˆœμ„œλ₯Ό 보μž₯ν•˜κΈ° μœ„ν•΄μ„œλŠ” μ„Έλͺ¨ν¬μ–΄λ₯Ό 0으둜 μ„€μ •ν•˜κ³ , μž…κΈˆν•  λ•Œ ν•΄μ œν•˜κ³  좜금 ν• λ•Œ νšλ“ν•˜λŠ” 방식을 μ‚¬μš©ν•˜λ©΄ μˆœμ„œλ₯Ό 보μž₯ν•  수 μžˆλ‹€.

728x90
λ°˜μ‘ν˜•
λŒ“κΈ€
κΈ€ 보관함
μ΅œκ·Όμ— 올라온 κΈ€
μ΅œκ·Όμ— 달린 λŒ“κΈ€