→ 동일한 다수의 스레드가 run() 메소드의 명령을 동시에 실행할 경우 메소드를 호출하여 필드값(공유)을 변경하면 잘못된 결과 발생 가능
◎스레드 동기화(Thread Synchronized) : 스레드에 의해 메소드 호출시 메소드의 모든 명령을 모두 처리하기 전까지 다른 스레드의 메소드 실행을 방지하기 위한 기능
→ 스레드를 일시 중지하여 명령이 실행되지 않도록 락(Lock) 기능 제공
- synchronized 키워드를 사용하여 메소드 선언 - 동기화 메소드(Synchronized Method)
형식) 접근제한자 synchronized 반환형 메소드명(자료형 매개변수명,...) {}- synchronized 키워드로 블럭을 설정하여 메소드 호출
형식) synchronized(객체) { 객체,메소드명(값,...);...}
→ 객체로 호출되는 모든 메소드는 동기화 처리되어 실행
package xyz.itwill.thread;
public class AccountUserApp {
public static void main(String[] args) {
//은행계좌정보를 생성하여 저장
Account account=new Account(10000);
/*
//단일 스레드(main)를 이용하여 은행계좌 사용자를 생성하여 입금 처리
AccountUser[] users=new AccountUser[3];
//모든 사용자가 동일한 계좌 사용
users[0]=new AccountUser(account, "홍길동");
users[1]=new AccountUser(account, "임꺽정");
users[2]=new AccountUser(account, "전우치");
for(AccountUser user:users) {
user.getAccount().deposit(user.getUserName(), 5000);
}
*/
//다중 스레드(main)를 이용하여 은행계좌 사용자를 생성하여 입금(출금) 처리
new AccountUser(account, "홍길동").start();
new AccountUser(account, "임꺽정").start();
new AccountUser(account, "전우치").start();
}
}
package xyz.itwill.thread;
//은행계좌정보(잔액)를 저장하기 위한 클래스
public class Account {
private int balance;
public Account() {
// TODO Auto-generated constructor stub
}
public Account(int balance) {
super();
this.balance = balance;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
//입금 처리 메소드 - 매개변수로 입금자와 입금액을 전달받아 처리
//public void deposit(String name, int amount) {
public synchronized void deposit(String name, int amount) {
balance+=amount;
System.out.println("[입금]"+name+"님이 "+amount+"원을 입금하여
잔액은 "+balance+"원입니다.");
}
//출금 처리 메소드 - 매개변수로 출금자와 출금액을 전달받아 처리
//public void withDraw(String name, int amount) {
public synchronized void withDraw(String name, int amount) {
if(balance<amount) {
System.out.println("[에러]"+name+"님, 잔액이 "+balance+"원
남아 "+amount+"원을 출금할 수 없습니다.");
return;
}
balance-=amount;
System.out.println("[출금]"+name+"님이 "+amount+"원을 출금하여
잔액은 "+balance+"원입니다.");
}
}
package xyz.itwill.thread;
//은행계좌 사용자정보(은행계좌정보, 사용자명)를 저장하기 위한 클래스
public class AccountUser extends Thread {
private Account account;//은행계좌정보 - 포함관계
private String userName;
public AccountUser() {
// TODO Auto-generated constructor stub
}
public AccountUser(Account account, String userName) {
super();
this.account = account;
this.userName = userName;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
public void run() {
// TODO Auto-generated method stub
// 프로그램 개발자에 의해 생성된 새로운 스레드가 run() 메소드의 명령 실행
// 은행계좌 사용자에 의한 입금 처리 메소드 호출
//account.deposit(userName, 5000);
synchronized (account) {
account.withDraw(userName, 5000);
}
}
}