JAVA

[Java] Thread Synchronization

lakelight 2022. 7. 29. 14:53
728x90
반응형

Thread Synchronization

두 개의 쓰레드가 동일한 객체에 접근을 하려고 할 때 공유 자원을 lock하여 다른 쓰레드가 접근하지 못하게 합니다. 그래서 두 개의 쓰레드가 공유자원에 동시에 접근하여 발생하는 문제를 없앨 수 있습니다.

이미지 출처: https://has3ong.github.io/computer%20science/critical-section/

 

Thread Synchronization Problem

package Java.thread.syncronizedEx;

import static java.lang.Thread.sleep;

class Bank{
    private int money = 10_000;

    public void saveMoney(int save){
        int curMoney = getMoney();

        try {
            sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        setMoney(curMoney + save);
    }

    public void minusMoney(int minus){
        int curMoney = getMoney();

        try {
            sleep(200);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        setMoney(curMoney - minus);
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}

class Save extends Thread{
    public void run(){
        System.out.println("start save");

        SyncMain.myBank.saveMoney(3000);
        System.out.println("saveMoney(3000): " + SyncMain.myBank.getMoney());
    }
}

class Minus extends Thread{
    public void run(){
        System.out.println("start minus");

        SyncMain.myBank.minusMoney(1000);
        System.out.println("minusMoney(1000): " + SyncMain.myBank.getMoney());
    }
}


public class SyncMain {

    public static Bank myBank = new Bank();

    public static void main(String[] args) throws InterruptedException {

        Save save = new Save();
        save.start();

        sleep(200);

        Minus minus = new Minus();
        minus.start();


        //결과

        /**
         * start save
         * start minus
         * minusMoney(1000): 9000
         * saveMoney(3000): 13000
         */
    }
}

 

문제

3000원을 저장하는 쓰레드는 작업이 3초가 걸리고 1000원을 사용하는 쓰레드는 0.2초가 걸립니다.
이 때 고유자원인 Bank에 두 쓰레드가 동시에 접근하기 때문에 결과 값이 원하는 값과 다르게 출력되었습니다.

이 문제를 해결하기 위해서는 3000원을 저장하는 쓰레드 작업과 1000원을 사용하는 쓰레드 작업이
동시에 실행되면 안됩니다. 즉 3000원을 저장하는 쓰레드 작업 수행 시 1000원을 사용하는 작업은 대기를 해야 합니다.

Bank는 공유자원이기 때문에 동기화를 해주어야합니다. 쓰레드가 사용중일 때는 lock을 걸고 사용이 끝난 후 lock을 풀어서
다른 쓰레드가 사용할 수 있도록 해야하는 것입니다.

 

Java Synchronized 메서드 구현

package Java.thread.syncronizedEx;

import static java.lang.Thread.sleep;

class Bank{
    private int money = 10_000;

//실제 동작하는 메서드에 synchronized 키워드 추가
    public synchronized void saveMoney(int save){
        int curMoney = getMoney();

        try {
            sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        setMoney(curMoney + save);
    }

//실제 동작하는 메서드에 synchronized 키워드 추가
    public synchronized void minusMoney(int minus){
        int curMoney = getMoney();

        try {
            sleep(200);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        setMoney(curMoney - minus);
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}

class Save extends Thread{
    public void run(){
        System.out.println("start save");

        SyncMain.myBank.saveMoney(3000);
        System.out.println("saveMoney(3000): " + SyncMain.myBank.getMoney());
    }
}

class Minus extends Thread{
    public void run(){
        System.out.println("start minus");

        SyncMain.myBank.minusMoney(1000);
        System.out.println("minusMoney(1000): " + SyncMain.myBank.getMoney());
    }
}


public class SyncMain {

    public static Bank myBank = new Bank();

    public static void main(String[] args) throws InterruptedException {

        Save save = new Save();
        save.start();

        sleep(200);

        Minus minus = new Minus();
        minus.start();


        //결과

        /**
         * start save
         * start minus
         * saveMoney(3000): 13000
         * minusMoney(1000): 12000
         */
    }
}

 

결론

Synchronized 키워드를 사용해서 멀티 쓰레드 동기화 작업을 해보았습니다.

728x90
반응형

'JAVA' 카테고리의 다른 글

[Java] Adapter Pattern  (0) 2022.07.31
[Java] Thread Method : wait(), notify()  (0) 2022.07.31
[Java] Thread Method : join()  (0) 2022.07.29
[Java] Priority Thread  (0) 2022.07.29
[Java] Thread  (0) 2022.07.29