Ga0Lee

[Java] 멀티스레드와 동시성 처리 Synchronized 본문

Java

[Java] 멀티스레드와 동시성 처리 Synchronized

가영리 2024. 11. 19. 09:00

Thread란

프로세스는 메모리나 CPU와 같은 자원을 할당 받아 실행 중인 프로그램(코드)을 말한다. 모든 프로세스는 하나 이상의 스레드가 존재하며, 두 개 이상의 스레드를 갖는 프로세스는 멀티 스레드 프로세스라고 한다.

스레드는 프로세스 내의 작업 단위로, 독자적인 메모리를 할당받은 프로세스의 메모리를 스레드끼리 공유할 수 있다.

특징 Single Threaded Multi-Threaded

스레드 수 1 2개 이상
작업 처리 방식 순차적으로 처리 동시에 처리
메모리 사용 간단한 메모리 구조 스레드 간 메모리 공유로 인해 동기화 관리 필요
CPU 활용 CPU가 하나의 작업만 처리하므로 활용도가 낮음 CPU가 동시에 여러 개의 작업을 처리하므로 활용도가 높음
계산기 프로그램, 동시성을 고려하지 않는 환경 동시에 여러 사용자의 요청을 처리하는 웹 서버, 데이터 처리 등 CPU를 많이 사용하는 작업

동시성을 처리하지 않으면 발생할 수 있는 문제를 간단히 살펴보자.

public class ThreadSynchronizedTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Task task = new Task();
        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.setName("t1-Thread");
        t2.setName("t2-Thread");

        t1.start();
        t2.start();
    }

}

class Account{
    int balance = 1000;

    public void withDraw(int money){

        if(balance >= money){
            try{
                Thread thread = Thread.currentThread();
                System.out.println(thread.getName() + " 출금 금액 ->> "+money);
                Thread.sleep(1000);
                balance -= money;
                System.out.println(thread.getName()+" balance:" + balance);

            }catch (Exception e) {}

        }
    }
}

class Task implements Runnable{
    Account acc = new Account();

    @Override
    public void run() {
        while(acc.balance > 0){
            // 100, 200, 300 중의 한 값을 임의로 선택해서 출금(withDraw)한다.
            int money = (int)(Math.random() * 3 + 1) * 100;
            acc.withDraw(money);

        }
    }
}
-------------------------------------------------------
t2-Thread 출금 금액 ->> 300
t1-Thread 출금 금액 ->> 100
t1-Thread balance:700
t2-Thread balance:700
t1-Thread 출금 금액 ->> 300
t2-Thread 출금 금액 ->> 200
t1-Thread balance:400
t2-Thread balance:200
t1-Thread 출금 금액 ->> 100
t2-Thread 출금 금액 ->> 100
t1-Thread balance:100
t1-Thread 출금 금액 ->> 100
t2-Thread balance:0
t1-Thread balance:-100

마지막 출력문을 확인했을 때 잔액이 음수가 되는 문제 상황이 발생한다.

그렇다면 이 문제를 해결할 수 있는 방법엔 무엇이 있을까

Synchronized

class Account{
    int balance = 1000;

    public **synchronized** void withDraw(int money){

        if(balance >= money){
            try{
                Thread thread = Thread.currentThread();
                System.out.println(thread.getName() + " 출금 금액 ->> "+money);
                Thread.sleep(1000);
                balance -= money;
                System.out.println(thread.getName()+" balance:" + balance);

            }catch (Exception e) {}

        }
    }
}

--------------------------------------------------------
t1-Thread 출금 금액 ->> 100
t1-Thread balance:900
t2-Thread 출금 금액 ->> 100
t2-Thread balance:800
t1-Thread 출금 금액 ->> 100
t1-Thread balance:700
t2-Thread 출금 금액 ->> 200
t2-Thread balance:500
t1-Thread 출금 금액 ->> 300
t1-Thread balance:200
t2-Thread 출금 금액 ->> 100
t2-Thread balance:100
t2-Thread 출금 금액 ->> 100
t2-Thread balance:0

잔액이 0으로 정상적으로 출력되는 것을 확인할 수 있다.