https://www.w3resource.com/java-tutorial/java-code-synchronization.php
Account : 공유하는 계좌 클래스
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package synchronization; public class Account { private int balance = 50; public int getBalance() { // TODO Auto-generated method stub return this.balance; } public void withdraw(int amount) { // TODO Auto-generated method stub this.balance -= amount; } } | cs |
Runnable 인터페이스의 구현객체 AccountTesting과 SynchronizedAccountTesting 구현하기.
AccountTesting의 makewithdrawal 메서드는 동기화되지 않은 메서드이고
SynchronizedAccountTesting의 makewithdrawal 메서드는 synchronized 키워드가 붙은 동기화 메서드
각 구현클래스에서 Account 타입의 공유객체를 생성하고
makewithdrawal 메서드에서
this.acct.withdraw(amount);
공유객체의 함수를 호출하여 balance값을 변경해주고 인출 완료 메시지를 프린트
start() 로 실행되는 run()메서드에서 makewithdrawal 메서드를 호출
사람 이름의 스레드를 두개 만들고 스레드를 실행.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | package synchronization; public class AccountTesting implements Runnable { private Account acct = new Account(); public static void main(String[] args) { AccountTesting r = new AccountTesting(); // Runnable 인터페이스 구현 클래스 객체를 매개값으로 직접 Thread 객체 생성 Thread one = new Thread(r); Thread two = new Thread(r); one.setName("Ranjeet"); two.setName("Reema"); one.start(); two.start(); } @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 5; i++) { this.makeWithdrawal(10); // 동기화메서드 호출 if (this.acct.getBalance() < 0) { System.out.println("account is overdrawn!"); } } } // 동기화 메서드 private void makeWithdrawal(int amount) { // TODO Auto-generated method stub if (this.acct.getBalance() >= amount) { System.out.println(Thread.currentThread().getName() + " is going to withdraw"); // [현재 스레드 이름] is going to withdraw try { Thread.sleep(100); } catch (InterruptedException e) { System.out.println(e.getMessage()); } this.acct.withdraw(amount); System.out.println(Thread.currentThread().getName() + " complete the withdrawal"); } else { System.out.println("Not enough in account for " + Thread.currentThread().getName() + "to withdraw " + this.acct.getBalance()); } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | package synchronization; public class SynchronizedAccountTesting implements Runnable { private Account acct = new Account(); public static void main(String[] args) { SynchronizedAccountTesting r = new SynchronizedAccountTesting(); // Runnable 인터페이스 구현 클래스 객체를 매개값으로 직접 Thread 객체 생성 Thread one = new Thread(r); Thread two = new Thread(r); one.setName("Ranjeet"); two.setName("Reema"); one.start(); two.start(); } @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 3; i++) { this.makeWithdrawal(10); // 동기화메서드 호출 if (this.acct.getBalance() < 0) { System.out.println("account is overdrawn!"); } } } // 동기화 메서드 private synchronized void makeWithdrawal(int amount) { // TODO Auto-generated method stub if (this.acct.getBalance() >= amount) { System.out.println(Thread.currentThread().getName() + " is going to withdraw"); // [현재 스레드 이름] is going to withdraw try { Thread.sleep(100); } catch (InterruptedException e) { System.out.println(e.getMessage()); } this.acct.withdraw(amount); System.out.println(Thread.currentThread().getName() + " complete the withdrawal"); } else { System.out.println("Not enough in account for " + Thread.currentThread().getName() + "to withdraw " + this.acct.getBalance()); } } } | cs |
AccountTesting타입을 매개값으로 받은 스레드는 동기화되지 않은 메서드를 사용하기때문에 스레드끼리 불규칙적으로 동시 실행된다.
SynchronizedAccountTesting타입을 매개값으로 받은 스레드는 동기화된 메서드를 사용하기때문에
한 스레드가 메서드를 사용하고 있을때 다른 (동기화 메서드를 사용할)스레드는 실행되지 않는다.
인출 메서드를 동기화하지 않으면 두 사람이 같은 계좌를 공유하여 동시에 인출하다가 잔액이 마이너스로 뜨는 오류가 생길 수 있다.
'Java > study' 카테고리의 다른 글
람다식(Lambda Expression) (0) | 2019.04.18 |
---|---|
제네릭(Generic) (0) | 2019.04.17 |
멀티스레드 (0) | 2019.04.16 |
Java 자주쓰는 단축키 모음 (0) | 2019.04.15 |
예외 처리 (0) | 2019.04.11 |