Thread 동기화 Remind

Thread-safe하기 위한 동기화 리마인드를 위한 소스.

ThreadSyncronizedTest.java
package com.practice;

public class ThreadSyncronizedTest {
    public static void main(String[] args) {

        Account humingAccount = new Account();

        humingAccount.setUserFullName("Huming");
        humingAccount.setUserNumber(0);
        humingAccount.setUserBalance(8000);

        System.out.println("Account Name is " + humingAccount.getUserFullName());
        System.out.println("Huming's initial balance : " + humingAccount.getUserBalance());

        //Run
        userTaskRunnable userTaskRunnable = new userTaskRunnable(humingAccount);

        Thread t1 = new Thread(userTaskRunnable);
        Thread t2 = new Thread(userTaskRunnable);

        t1.setName("t1_Thread");
        t2.setName("t2_Thread");

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

    }
}

class Account {
    int userNumber;
    String userFullName;
    double userBalance;

    public void setUserNumber(int userNumber) {
        this.userNumber = userNumber;
    }

    public void setUserFullName(String userFullName) {
        this.userFullName = userFullName;
    }

    public void setUserBalance(double userBalance) {
        this.userBalance = userBalance;
    }

    public int getUserNumber() {
        return userNumber;
    }

    public String getUserFullName() {
        return userFullName;
    }

    public double getUserBalance() {
        return userBalance;
    }

    public boolean deposit(double amount ) {
        double newBalance;
        synchronized (this) {
            if (amount < 0.0) {
                return false;
            } else {
                newBalance = userBalance + amount;
                userBalance = newBalance;
                return true;
            }
        }
    }
    public boolean withdraw( double amount ) {
        double newBalance;
        // syncronized 를 사용하여 쓰레드 safe 하게 작성
        synchronized (this) {
            if (amount > userBalance) {
                return false;
            } else {
                try {
                    Thread thread = Thread.currentThread();
                    System.out.println(thread.getName() + ">> Witdraw Amount : " + amount);
                    //Thread.sleep(1000);
                    newBalance = userBalance - amount;
                    userBalance = newBalance;
                    System.out.println(thread.getName() + ">> Balance : " + userBalance);
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
        }
    }
}
userTaskRunnable.java
package com.practice;

public class userTaskRunnable implements Runnable {
    Account userAccount;
    public userTaskRunnable(Account _userAccount) {
       this.userAccount = _userAccount;
    }

    public void run() {
        while(userAccount.userBalance > 0) {
            double money = 100.0;
            userAccount.withdraw(money);
        }
    }
}
  • main 함수에서 쓰레드를 작동시키면, runnable을 통해 쓰레드별로 withdraw(money) 호출
  • synchronized 미사용의 경우,
    • newBalance = userBalance – amount; 까지 처리 후.. userBalance가 처리되지 않은 상태에서 타쓰레드로 컨텍스트 스위칭이 발생한다고 가정하자.
  • t1 에서 100달러 차감 후, userBalance가 갱신되지 않은 상태에서 t2의 100달러가 차감되므로 잔고는 여전히 900원. (t1과 t2가 100달러씩 200달러를 차감했지만, 잔고는 갱신되지 않았다)
  • syncronized를 사용하여 쓰레드 동기화 (타쓰레드 블록킹)을 시행함으로써 클래스 데이터의 변경을 방지할 수 있다.

답글 남기기