프로그래밍 정리/자바

synchronized

주누다 2013. 6. 17. 15:51
반응형

- synchronized는 메서드와 블록 형태로 사용할 수 있으며, synchronized 메서드로 사용될 경우 해당 메서드 내에서 사용되는 모든 멤버 변수들은 락(Lock)이 걸리게 됨.


- synchronized 메서드의 예

-> public synchronized void saveMoney(int save){

// .... 공유자원 - 멤버의 사용

}


-> synchronized 블록의 예

=> 만약 블록 형태로 사용된다면 블록에서 명시한 객체의 멤버들은 모두 락(Lock)에 걸리게 됨.

public void saveMoney(int save){

synchronized(this){

// ...공유자원 - 멤버의 사용

}

}

// synchronized 메서드나 블록 내에서 사용되는 공유자원은 무조건 동기화가 보장됨.


============================================================================================================



public class Bank {


private int money = 10000; // 예금 잔액

public int getMoney(){

return this.money;

}

public void setMoney(int money){

this.money = money;

}

public void saveMoney(int save){

synchronized (this) {

int m = this.getMoney();

try{

Thread.sleep(3000);

}catch (Exception e) {

// TODO: handle exception

}

this.setMoney(m + save);

}

}

// 또는 public void synchronized void saveMoney(int save){


public void minusMoeny(int minus){

synchronized (this) {

int m = this.money;

try{

Thread.sleep(2000);

}catch (Exception e) {

// TODO: handle exception

}

this.setMoney(m - minus);

}

}

// 또는 public void synchronized void minusMoney(int save){

}




public class Park extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
NotSyncMain.myBank.saveMoney(3000);
System.out.println("minusMoney(3000) : " + NotSyncMain.myBank.getMoney());
}
}



public class ParkWife extends Thread{

@Override

public void run() {

// TODO Auto-generated method stub

NotSyncMain.myBank.minusMoeny(1000);

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

}

}



public class NotSyncMain {

public static Bank myBank = new Bank();
public static void main(String[] args) {
Park p = new Park();
ParkWife w = new ParkWife();
p.start();
try{
Thread.sleep(200);
}catch (Exception e) {
// TODO: handle exception
}
w.start();
}
}
============================================================================================================

- synchronized 메서드
-> public synchronized void saveMoney(int save){
// 메서드 내에 사용된 멤버 변수들의 동기화가 보장.
}

-> public synchronized void minusMoney(int minus){
// 메서드 내에 사용된 멤버 변수들의 동기화가 보장.
}

- synchronized는 synchronized 메서드가 위치한 클래스의 멤버 젼수를 사용할 때, 해당 멤버 변수의 메모리를 잠그는(Lock) 방법으로 다른 쓰레드가 해당 자원에 접근하면 자동으로 대기시키게 만듬. synchronized 키워드를 메서드 앞에 붙여주면 해당 메서드 내에 존재하는 모든 멤버 변수를 모두 동기화시키게 됨. 하지만 동기화할 필요가 없는 자원도 있을 수 있음.
이를 위해서 메서드 내에 특정구간만 동기화시키고자 할 때는 다음과 같이 synchronzied블록을 이용하면 됨.
-> synchronized 블록을 사용한 saveMoney() 메서드
public void saveMoney(int save){
synchronized(this){
// 블록 내에 사용된 this. 즉 현재 클래스의 멤버 변수들에 대한 동기화가 보장.
}
}

-> synchronized 블록을 사용한 minusMoney() 메서드
public void minusMoney(int minus){
synchronized(this){
// 블록 내에 사용된 this. 즉 현재 클래스의 멤버 변수들에 대한 동기화가 보장.
}
}

- 주의 사항
-> synchronized의 괄호에 들어가는 this. synchronized 블록을 사용할 때 괄호안에 사용된 객체의 의미는 공유자원이 어디에 존재하는가의 문제. 공유자원이 현재의 클래스에 존재하기 때문에 synchronized 괄호안에 this가 사용된 것.
 현재 클래스의 멤버가 공유자원이면 현재 클래스를 의미하는 this를 사용하시면 됨. 위의 예는 synchronized 메서드와 synchronized 블록을 둘 다 보여주고 있음. Park p의 run() 내에 존재하는 synchronized된 부분이 끝나기 전까지는 ParkWife w의 run()은 대기하게 될 것.



반응형

'프로그래밍 정리 > 자바' 카테고리의 다른 글

synchronized의 한계  (0) 2013.06.17
synchronized의 활용  (0) 2013.06.17
공유자원의 접근  (0) 2013.06.17
멀티쓰레드와 문제점  (0) 2013.06.17
쓰레드 죽이기  (0) 2013.06.17